2020面試整理【java】
spring面試題
1.你對spring的了解
Spring 是個Java企業級應用的開源開發架構。
Spring主要用來開發Java應用,但是有些擴充是針對建構J2EE平台的web應用。
Spring 架構目标是簡化Java企業級應用開發,它使得開發者隻需要關心業務需求。
2.spring 的優缺點
Spring 的核心概念是IOC和AOP,這兩個核心服務的對象算是bean(POJO),定位是一個輕量級的架構
它具備以下優點:
spring中避免了關鍵字new造成的耦合問題;
spring本身就是一個工廠,不需要再編寫工廠類了;
spring不需要進行明确的引用關系的傳遞,直接通過配置完成;
所有架構幾乎都可以在spring中整合在一起使用;
spring程式設計=factory設計模式+proxy設計模式
當然,它的缺點也是不少的:
spring基于大量的xml 配置檔案,使得我們花了大量的時間放在配置上,拖慢了開發的進度,springboot 問世後,提倡代碼優于配置解決了這個問題。
spring 的内容太龐大,随便打斷點檢視的時候會出現十幾二十層代碼,閱覽性不強,在實際開發的過程中spring的角色更像是膠水一樣,充當整合各種技術的角色,同時作為bean的容器。
3.spring的核心技術(IOC、DI、AOP)
(1)IOC:控制反轉,把建立對象的控制權利由代碼轉移到spring的配置檔案中,對象的建立不用去new了,可以由spring自動生産,使用java的反射機制,根據配置檔案在運作時動态的去建立對象以及管理對象,并調用對象的方法的。
實作原理:工廠模式加反射機制
兩種 IOC 容器:
- BeanFactory - BeanFactory 就像一個包含 bean 集合的工廠類。它會在用戶端要求時執行個體化 bean。
- ApplicationContext - ApplicationContext 接口擴充了 BeanFactory 接口。它在 BeanFactory 基礎上提供了一些額外的功能。
(2)DI:依賴注入,在程式運作期間,由外部容器動态地将依賴對象注入到元件中。簡單定義就是當一個對象需要另一個對象時,可以把另一個對象注入到對象中去。
注入的方式:
- 構造注入
- Set注入
- 接口注入
(3)AOP:面向切面程式設計,系統中有很多各不相幹的類的方法,在這衆多方法中加入某種系統功能的代碼,如加入日志,權限判斷等,AOP可以實作橫切關注點(如日志,安全,緩存和事務管理)與他們所影響的對象之間的解耦。
實作原理:動态代理
Spring AOP and AspectJ AOP 差別:
- Spring AOP 基于動态代理方式實作;AspectJ 基于靜态代理方式實作。
- Spring AOP 僅支援方法級别的 PointCut;提供了完全的 AOP 支援,它還支援屬性級别的 PointCut。
實作AOP 功能采用的是代理技術,調用代理類,代理類與目标類具有相同的方法聲明。
AOP 在spring中主要表現在兩個方面:提供聲明式的事務管理 、spring支援使用者自定義切面。
AOP主要包括通知(Advice)切點(PointCut)連接配接點(JoinPoint)
springboot 中使用AOP的代碼執行個體:
<!-- aop -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
@Aspect
@Component
public class ControllerInterceptor {
private final Logger logger = LogManager.getLogger(this.getClass());
@Pointcut("execution(public * com.example.homework.controller..*(..))")
public void controllerMethodPointcut(){}
@Before("controllerMethodPointcut()") //指定攔截器規則
public Object interceptor(JoinPoint jp){
MethodSignature signature = (MethodSignature) jp.getSignature();
Method method = signature.getMethod(); //擷取被攔截的方法
String methodName = method.getName(); //擷取被攔截的方法名
logger.info("interceptor ***************************");
logger.info("methodName: "+methodName);
return null;
}
}
4.spring中Bean的作用域
singleton:prototype:Spring IoC容器中隻會存在一個共享的Bean執行個體,無論有多少個Bean引用它,始終指向同一對象。Singleton作用域是Spring中的預設作用域。
request:每次通過Spring容器擷取prototype定義的bean時,容器都将建立一個新的Bean執行個體,每個Bean執行個體都有自己的屬性和狀态,而singleton全局隻有一個對象。
session:在一次Http請求中,容器會傳回該Bean的同一執行個體。而對不同的Http請求則會産生新的Bean,而且該bean僅在目前Http Request内有效。
global Session:在一次Http Session中,容器會傳回該Bean的同一執行個體。而對不同的Session請求則會建立新的執行個體,該bean執行個體僅在目前Session内有效。
在一個全局的Http Session中,容器會傳回該Bean的同一個執行個體,僅在使用portlet context時有效。
5.Spring JDBC API 中存在哪些類?
- JdbcTemplate
- SimpleJdbcTemplate
- NamedParameterJdbcTemplate
- SimpleJdbcInsert
- SimpleJdbcCall
6.Spring 支援的事務管理類型
- 程式化事務管理:在此過程中,在程式設計的幫助下管理事務。它為您提供極大的靈活性,但維護起來非常困難。
- 聲明式事務管理:在此,事務管理與業務代碼分離。僅使用注解或基于 XML 的配置來管理事務。
7.spring與springmvc的差別
Spring是IOC和AOP的容器架構,SpringMVC是基于Spring功能之上添加的Web架構,想用SpringMVC必須先依賴Spring。
springmvc面試題
1.什麼是Spring MVC ?簡單介紹下你對springMVC的了解?
Spring MVC是一個基于Java的實作了MVC設計模式的請求驅動類型的輕量級Web架構,
通過把Model,View,Controller分離,将web層進行職責解耦,把複雜的web應用分成邏輯清晰的幾部分,
簡化開發,減少出錯,友善組内開發人員之間的配合。
2.SpringMVC的流程?
(1)使用者發送請求至前端控制器DispatcherServlet; (2) DispatcherServlet收到請求後,調用HandlerMapping處理器映射器,請求擷取Handle; (3)處理器映射器根據請求url找到具體的處理器,生成處理器對象及處理器攔截器(如果有則生成)一并傳回給DispatcherServlet; (4)DispatcherServlet 調用 HandlerAdapter處理器擴充卡; (5)HandlerAdapter 經過适配調用 具體處理器(Handler,也叫後端控制器); (6)Handler執行完成傳回ModelAndView; (7)HandlerAdapter将Handler執行結果ModelAndView傳回給DispatcherServlet; (8)DispatcherServlet将ModelAndView傳給ViewResolver視圖解析器進行解析; (9)ViewResolver解析後傳回具體View; (10)DispatcherServlet對View進行渲染視圖(即将模型資料填充至視圖中) (11)DispatcherServlet響應使用者。
3.Springmvc的優點
(1)可以支援各種視圖技術,而不僅僅局限于JSP;
(2)與Spring架構內建(如IoC容器、AOP等);
(3)清晰的角色配置設定:前端控制器(dispatcherServlet) , 請求到處理器映射(handlerMapping), 處理器擴充卡(HandlerAdapter), 視圖解析器(ViewResolver)。
(4) 支援各種請求資源的映射政策。
4.Spring MVC的主要元件?
(1)前端控制器 DispatcherServlet(不需要程式員開發)
作用:接收請求、響應結果,相當于轉發器,有了DispatcherServlet 就減少了其它元件之間的耦合度。
(2)處理器映射器HandlerMapping(不需要程式員開發)
作用:根據請求的URL來查找Handler
(3)處理器擴充卡HandlerAdapter
注意:在編寫Handler的時候要按照HandlerAdapter要求的規則去編寫,這樣擴充卡HandlerAdapter才可以正确的去執行Handler。
(4)處理器Handler(需要程式員開發)
(5)視圖解析器 ViewResolver(不需要程式員開發)
作用:進行視圖的解析,根據視圖邏輯名解析成真正的視圖(view)
(6)視圖View(需要程式員開發jsp)
View是一個接口, 它的實作類支援不同的視圖類型(jsp,freemarker,pdf等等)
6.SpringMVC怎麼樣設定重定向和轉發的?
(1)轉發:在傳回值前面加"forward:",譬如"forward:user.do?name=method4"
(2)重定向:在傳回值前面加"redirect:",譬如"redirect:http://www.baidu.com"
7.GET和POST差別?
注解配置:@RequestMapping注解裡面加上method=RequestMethod.GET
url可見性
get,參數url可見;
post,url參數不可見
資料傳輸上
get,通過拼接url進行傳遞參數;
post,通過body體傳輸參數
緩存性
get請求是可以緩存的
post請求不可以緩存
後退頁面的反應
get請求頁面後退時,不産生影響
post請求頁面後退時,會重新送出請求
傳輸資料的大小
get一般傳輸資料大小不超過2k-4k(根據浏覽器不同,限制不一樣,但相差不大)
post請求傳輸資料的大小根據php.ini 配置檔案設定,也可以無限大
安全性
這個也是最不好分析的,原則上post肯定要比get安全,畢竟傳輸參數時url不可見,但也擋不住部分人閑的沒事在那抓包玩。安全性個人覺得是沒多大差別的,防君子不防小人就是這個道理。對傳遞的參數進行加密,其實都一樣。
8.cookie和session的差別?
(1)cookie資料存放在客戶的浏覽器上,session資料放在伺服器上 (2)cookie不是很安全,别人可以分析存放在本地的COOKIE并進行COOKIE欺騙,如果主要考慮到安全應當使用session (3)session會在一定時間内儲存在伺服器上。當通路增多,會比較占用你伺服器的性能,如果主要考慮到減輕伺服器性能方面,應當使用COOKIE (4)單個cookie在用戶端的限制是3K,就是說一個站點在用戶端存放的COOKIE不能3K。 (5)将登陸資訊等重要資訊存放為SESSION;其他資訊如果需要保留,可以放在COOKIE中
springboot面試題
1.為什麼要用springboot?
能夠簡化搭建Spring項目的過程,省去了繁雜的配置過程,對開發者更友好
- 用來簡化Spring應用的初始搭建以及開發過程,使用特定的方式來進行配置
- 建立獨立的Spring引用程式main方法運作
- 嵌入的tomcat無需部署war檔案
- 簡化maven配置
- 自動配置Spring添加對應的功能starter自動化配置
2.Spring Boot有哪些優點
(1) 能夠獨立運作:内置了servlet容器
(2) 配置簡單:搭建項目不再需要繁瑣的配置
(3) 自動配置:根據目前類路徑下的類和jar包自動配置bean
(4) 無代碼生成和XML配置:在配置過程中沒有代碼生成,也不需要XML檔案,完全通過注解實作
(5) 應用監控:提供監控服務,便于做健康檢測
3.Spring Boot有哪些核心配置檔案
(1) bootstrap(.yml或者.properties):bootstrap是應用程式的父上下文,擁有更高的加載優先級,主要用于從額外的資源來加載配置資訊,還可以在本地外部配置檔案中解密屬性。這兩個上下文共用一個環境,它是任何Spring應用程式的外部屬性的來源。bootstrap 裡面的屬性會優先加載,它們預設也不能被本地相同配置覆寫。
(2) application(.yml或者.properties):主要用于Sprint Boot項目的自動化配置。
4.Spring Boot 的配置檔案有哪幾種格式
.properties和.yml兩種格式,主要的差別在于書寫方式不同
(1) .properties
(2) .ymlapp.user.name = javastack
app: user: name: javastack
5.Spring Boot 實作熱部署有哪幾種方式
主要有兩種方式:(1)Spring Loaded (2) Spring-boot-devtools
6.運作SpringBoot有幾種方式?
- 打包用指令或者放到容器中運作
- 用Maven或Gradle插件運作
- 直接執行main方法運作
7.springboot四大特性
- Starter添加項目依賴
- bean的自動化配置
Spring Boot CLI與Groovy的高效配合
Spring Boot CLI充分利用了Spring Boot Starter和自動配置的魔力,并添加了一些Groovy的功能。它簡化了Spring的開發流程,通過CLI,我們能夠運作一個或多個Groovy腳本,并檢視它是如何運作的。在應用的運作過程中,CLI能夠自動導入Spring類型并解析依賴
Spring Boot Actuator
完成的主要功能就是為基于Spring Boot的應用添加多個有用的管理端點
8.什麼是Swagger?你用Spring Boot實作了嗎?
Swagger 廣泛用于可視化 API,使用 Swagger UI 為前端開發人員提供線上沙箱。Swagger 是用于生成 RESTful Web 服務的可視化表示的工具,規範和完整架構實作。它使文檔能夠以與伺服器相同的速度更新。當通過 Swagger 正确定義時,消費者可以使用最少量的實作邏輯來了解遠端服務并與其進行互動。是以,Swagger消除了調用服務時的猜測。
9.什麼是FreeMarker模闆?
FreeMarker 是一個基于 Java 的模闆引擎,最初專注于使用 MVC 軟體架構進行動态網頁生成。使用 Freemarker 的主要優點是表示層和業務層的完全分離。程式員可以處理應用程式代碼,而設計人員可以處理 html 頁面設計。最後使用freemarker 可以将這些結合起來,給出最終的輸出頁面。
10.springboot常用注解?
(1)啟動注解 @SpringBootApplication
檢視源碼可發現,@SpringBootApplication是一個複合注解,包含了@SpringBootConfiguration,@EnableAutoConfiguration,@ComponentScan這三個注解
mybatis面試題
1.MyBatis 的好處是什麼,為什麼用mybatis等?(多次被問到)
(1) MyBatis 把 sql 語句從 Java 源程式中獨立出來,放在單獨的 XML 檔案中編寫,給程式的 維護帶來了很大便利。 (2)MyBatis 封裝了底層 JDBC API 的調用細節,并能自動将結果集轉換成 Java Bean 對象, 大大簡化了 Java 資料庫程式設計的重複工作。 (3)因為 MyBatis 需要程式員自己去編寫 sql 語句,程式員可以結合資料庫自身的特點靈活 控制 sql 語句,是以能夠實作比 Hibernate 等全自動 orm 架構更高的查詢效率,能夠完成複 雜查詢。
2.mybatis與hibernate的差別在哪裡?(多次被問到)
(1)兩者最大的差別
針對簡單邏輯,Hibernate和MyBatis都有相應的代碼生成工具,可以生成簡單基本的DAO層方法;
針對進階查詢,Mybatis需要手動編寫SQL語句,以及ResultMap。而Hibernate有良好的映射機制,開發者無需關心SQL的生成與結果映射,可以更專注于業務流程。
(2)開發難度對比
Hibernate的開發難度要大于Mybatis。主要由于Hibernate比較複雜、龐大,學習周期較長。
而Mybatis則相對簡單一些,并且Mybatis主要依賴于sql的書寫,讓開發者感覺更熟悉。
(3)sql書寫比較
Mybatis的SQL是手動編寫的,是以可以按需求指定查詢的字段。不過沒有自己的日志統計,是以要借助log4j來記錄日志。
Hibernate也可以自己寫SQL來指定需要查詢的字段,但這樣就破壞了Hibernate開發的簡潔性。不過Hibernate具有自己的日志統計。
(4)資料庫擴充性比較
Mybatis由于所有SQL都是依賴資料庫書寫的,是以擴充性,遷移性比較差。
Hibernate與資料庫具體的關聯都在XML中,是以HQL對具體是用什麼資料庫并不是很關心。
(5)緩存機制比較(如果不知道緩存機制,建議不要說)
相同點:Hibernate和Mybatis的二級緩存除了采用系統預設的緩存機制外,都可以通過實作你自己的緩存或為其他第三方緩存方案,建立擴充卡來完全覆寫緩存行為。
不同點:Hibernate的二級緩存配置在SessionFactory生成的配置檔案中進行詳細配置,然後再在具體的表-對象映射中配置是那種緩存。
MyBatis的二級緩存配置都是在每個具體的表-對象映射中進行詳細配置,這樣針對不同的表可以自定義不同的緩存機制。并且Mybatis可以在命名空間***享相同的緩存配置和執行個體,通過Cache-ref來實作。
兩者比較:因為Hibernate對查詢對象有着良好的管理機制,使用者無需關心SQL。是以在使用二級緩存時如果出現髒資料,系統會報出錯誤并提示。
而MyBatis在這一方面,使用二級緩存時需要特别小心。如果不能完全确定資料更新操作的波及範圍,避免Cache的盲目使用。否則,髒資料的出現會給系統的正常運作帶來很大的隐患。
3.#{}和${}的差別是什麼?
${}是Properties檔案中的變量占位符,它可以用于标簽屬性值和sql内部,屬于靜态文本替換,比如${driver}會被靜态替換為com.mysql.jdbc.Driver。
#{}是sql的參數占位符,Mybatis會将sql中的#{}替換為?号,在sql執行前會使用PreparedStatement的參數設定方法,按序給sql的?号占位符設定參數值,比如ps.setInt(0, parameterValue),#{item.name}的取值方式為使用反射從參數對象中擷取item對象的name屬性值,相當于param.getItem().getName()。
不同點:
#{}是預編譯處理,${}是字元串替換。
Mybatis在處理#{}時,會将sql中的#{}替換為?号,調用PreparedStatement的set方法來指派,可以有效的防止SQL注入,提高系統安全性;
在處理${}時,就是把${}替換成變量的值,一般用于傳入資料庫對象,例如傳入表名。
用法:
select * from user where name = #{name}; select * from user where name = '${name}'; 必須加單引号
4.Xml映射檔案中,除了常見的select|insert|updae|delete标簽之外,還有哪些标簽?
<resultMap>、<parameterMap>、<sql>、<include>、<selectKey>,加上動态sql的9個标簽,trim|where|set|foreach|if|choose|when|otherwise|bind等,其中<sql>為sql片段标簽,通過<include>标簽引入sql片段,<selectKey>為不支援自增的主鍵生成政策标簽。
bind 元素标簽可以從 OGNL 表達式中建立一個變量井将其綁定到上下文中,MyBatis中使用mysql的模糊查詢字元串拼接(like) 中也涉及到bind的使用。建立一個 bind 元素标簽的變量後 ,就可以在下面直接使用,使用 bind 拼接字元串不僅可以避免因更換資料庫而修改 SQL,也能預防 SQL 注入。
<select id="getEmpsTestInnerParameter" resultType="com.hand.mybatis.bean.Employee"> <!-- bind:可以将OGNL表達式的值綁定到一個變量中,友善後來引用這個變量的值 --> <bind name="bindeName" value="'%'+eName+'%'"/> eName是employee中一個屬性值 SELECT * FROM emp <if test="_parameter!=null"> where ename like #{bindeName} </if> </select>
5.Mybatis是如何進行分頁的?分頁插件的原理是什麼?
Mybatis使用RowBounds對象進行分頁,它是針對ResultSet結果集執行的記憶體分頁,而非實體分頁,可以在sql内直接書寫帶有實體分頁的參數來完成實體分頁功能,也可以使用分頁插件來完成實體分頁。
分頁插件的基本原理是使用Mybatis提供的插件接口,實作自定義插件,在插件的攔截方法内攔截待執行的sql,然後重寫sql,根據dialect方言,添加對應的實體分頁語句和實體分頁參數。
舉例:select * from student,攔截sql後重寫為:select t.* from (select * from student)t limit 0,10
mybatis的兩種分頁方式:RowBounds和PageHelper
6.Mybatis執行批量插入,能傳回資料庫主鍵清單嗎?
能,JDBC都能,Mybatis當然也能。
1、對于支援生成自增主鍵的資料庫:增加 useGenerateKeys和keyProperty ,<insert>标簽屬性。
2、不支援生成自增主鍵的資料庫:使用<selectKey>。
7.mybatis傳遞參數的方式(4種)?
(1)順序傳遞參數
mapper.java檔案:
mapper.xml檔案:public User selectUser(String name, int deptId);
<select id="selectUser" resultType="com.wyj.entity.po.User"> select * from user where userName = #{0} and deptId = #{1} </select>
(2)注解@Param傳遞參數
mapper.java檔案:
mapper.xml檔案:public User selectUser(@Param("userName") String name, int @Param("deptId") id);
<select id="selectUser" resultType="com.wyj.entity.po.User"> select * from user where userName = #{userName} and deptId = #{deptId} </select>
(3)使用Map集合傳遞參數
mapper.java檔案:
mapper.xml檔案:public User selectUser(Map<String, Object> params);
<select id="selectUser" parameterType="java.util.Map" resultType="com.wyj.entity.po.User"> select * from user where userName = #{userName} and deptId = #{deptId} </select>
(4)使用JavaBean實體類傳遞參數
mapper.java檔案:
mapper.xml檔案:public User selectUser(User user);
<select id="selectUser" parameterType="com.wyj.entity.po.User" resultType="com.wyj.entity.po.User"> select * from user where userName = #{userName} and deptId = #{deptId} </select>
8.mybatis中模糊查詢(mysql)
<select id="selectLikeTwo" resultType="com.bjpowernode.domain.Student"> select * from student where name like "%" #{name} "%" </select>
線程面試題
1.建立線程有哪些方法(4種)?
- 繼承Thread類,重寫run方法(其實Thread類本身也實作了Runnable接口)
- 實作Runnable接口,重寫run方法
- 實作Callable接口,重寫call方法(有傳回值)
- 使用線程池(有傳回值)
2.線程的生命周期
線程的生命周期包含5個階段,包括:建立、就緒、運作、阻塞、銷毀。
- 建立:就是剛使用new方法,new出來的線程;
- 就緒:就是調用的線程的start()方法後,這時候線程處于等待CPU配置設定資源階段,誰先搶的CPU資源,誰開始執行;
- 運作:當就緒的線程被排程并獲得CPU資源時,便進入運作狀态,run方法定義了線程的操作和功能;
- 阻塞:在運作狀态的時候,可能因為某些原因導緻運作狀态的線程變成了阻塞狀态,比如sleep()、wait()之後線程就處于了阻塞狀态,這個時候需要其他機制将處于阻塞狀态的線程喚醒,比如調用notify或者notifyAll()方法。喚醒的線程不會立刻執行run方法,它們要再次等待CPU配置設定資源進入運作狀态;
- 銷毀:如果線程正常執行完畢後或線程被提前強制性的終止或出現異常導緻結束,那麼線程就要被銷毀,釋放資源;
完整的生命周期圖如下:
3.Runnable和Callable的差別?
相同點:兩者都需要調用Thread.start啟動線程
不同點:
- Callable接口的call()方法有傳回值;而實作Runnable接口的run()方法沒有傳回值
- Callable接口的call()方法允許抛出異常;而Runnable接口的run()方法的異常隻能在内部消化,不能繼續上抛
4.start()和run()方法有什麼差別?
start()方法被用來啟動新建立的線程,而且start()内部調用了run()方法;
run( )方法是一個普通方法,當你調用run()方法的時候,隻會是在原來的線程中調用,沒有新的線程啟動。
- start()方法功能介紹 start()方法來啟動線程,真正實作了多線程運作。 start方法的作用就是将線程由建立狀态,變為就緒狀态。當線程建立成功時,線程處于建立狀态,如果你不調用start( )方法,那麼線程永遠處于建立狀态。調用start( )後,才會變為就緒狀态,線程才可以被CPU運作。
- start()執行時間 調用start( )方法後,線程的狀态是就緒狀态,而不是運作狀态(關于線程的狀态詳細。線程要等待CPU排程,不同的JVM有不同的排程算法,線程何時被排程是未知的。是以,start()方法的被調用順序不能決定線程的執行順序。
- 注意 由于線上程的生命周期中,線程的狀态由建立到就緒隻會發生一次,是以,一個線程隻能調用start()方法一次,多次啟動一個線程是非法的。特别是當線程已經結束執行後,不能再重新啟動。
5.線程池有哪些參數
最常用的三個參數:
corePoolSize:核心線程數 queueCapacity:任務隊列容量(阻塞隊列) maxPoolSize:最大線程數
三個參數的作用:
當線程數小于核心線程數時,建立線程。 當線程數大于等于核心線程數,且任務隊列未滿時,将任務放入任務隊列。 當線程數大于等于核心線程數,且任務隊列已滿 若線程數小于最大線程數,建立線程 若線程數等于最大線程數,抛出異常,拒絕任務
6.線程池有幾種(5種)?拒絕政策有幾種(4種)?阻塞隊列有幾種(3種)?
五種線程池:
- ExecutorService threadPool = null;
- threadPool = Executors.newCachedThreadPool();//有緩沖的線程池,線程數 JVM 控制
- threadPool = Executors.newFixedThreadPool(3);//固定大小的線程池
- threadPool = Executors.newScheduledThreadPool(2);//一個能實作定時、周期性任務的線程池
- threadPool = Executors.newSingleThreadExecutor();//單線程的線程池,隻有一個線程在工作
- threadPool = new ThreadPoolExecutor();//預設線程池,可控制參數比較多
四種拒絕政策:
- RejectedExecutionHandler rejected = null;
- rejected = new ThreadPoolExecutor.AbortPolicy();//預設,隊列滿了丢任務抛出異常
- rejected = new ThreadPoolExecutor.DiscardPolicy();//隊列滿了丢任務不異常
- rejected = new ThreadPoolExecutor.DiscardOldestPolicy();//将最早進入隊列的任務删,之後再嘗試加入隊列
- rejected = new ThreadPoolExecutor.CallerRunsPolicy();//如果添加到線程池失敗,那麼主線程會自己去執行該任務
三種阻塞隊列:
- BlockingQueue<Runnable> workQueue = null;
- workQueue = new ArrayBlockingQueue<>(5);//基于數組的先進先出隊列,有界
- workQueue = new LinkedBlockingQueue<>();//基于連結清單的先進先出隊列,***
- workQueue = new SynchronousQueue<>();//無緩沖的等待隊列,***
7.死鎖
什麼叫死鎖?
所謂死鎖,是指多個程序在運作過程中因争奪資源而造成的一種僵局,當程序處于這種僵持狀态時,若無外力作用,它們都将無法再向前推進。 舉個例子來描述,如果此時有一個線程A,按照先鎖a再獲得鎖b的的順序獲得鎖,而在此同時又有另外一個線程B,按照先鎖b再鎖a的順序獲得鎖。
産生死鎖的原因?
(1) 因為系統資源不足。 (2) 程序運作推進的順序不合适。 (3) 資源配置設定不當等。
死鎖産生的4個必要條件?
(1) 互斥條件:程序要求對所配置設定的資源進行排它性控制,即在一段時間内某資源僅為一程序所占用。 (2) 請求和保持條件:當程序因請求資源而阻塞時,對已獲得的資源保持不放。 (3) 不剝奪條件:程序已獲得的資源在未使用完之前,不能剝奪,隻能在使用完時由自己釋放。 (4) 環路等待條件:在發生死鎖時,必然存在一個程序--資源的環形鍊。
預防和處理死鎖的方法?
(1)盡量不要在釋放鎖之前競争其他鎖 一般可以通過細化同步方法來實作,隻在真正需要保護共享資源的地方去拿鎖,并盡快釋放鎖,這樣可以有效降低 在同步方法裡調用其他同步方法的情況 (2)順序索取鎖資源 如果實在無法避免嵌套索取鎖資源,則需要制定一個索取鎖資源的政策,先規劃好有哪些鎖,然後各個線程按照一個順序去索取,不要出現上面那個例子中不同順序,這樣就會有潛在的死鎖問題 (3)嘗試定時鎖 在索取鎖的時候可以設定一個逾時時間,如果超過這個時間還沒索取到鎖,則不會繼續堵塞而是放棄此次任務
解除死鎖的方法?
(1)剝奪資源:從其它程序剝奪足夠數量的資源給死鎖程序,以解除死鎖狀态; (2)撤消程序:可以直接撤消死鎖程序或撤消代價最小的程序,直至有足夠的資源可用,死鎖狀态.消除為止;所謂代價是指優先級、運作代價、程序的重要性和價值等。
如何檢測死鎖?
(1)利用Java自帶工具JConsole (2)Java線程死鎖檢視分析方法
8.volatile底層是怎麼實作的?
當一個變量定義為volatile後,它将具備兩種特性:1. 可見性,2. 禁止指令重排序。
可見性:編譯器為了加快程式運作速度,對一些變量的寫操作會現在寄存器或CPU緩存上進行,最後寫入記憶體。而在這個過程中,變量的新值對其它線程是不可見的。當對volatile标記的變量進行修改時,先目前處理器緩存行的資料寫回到系統記憶體,然後這個寫回記憶體的操作會使其他CPU裡緩存了該記憶體位址的資料無效。
處理器使用嗅探技術保證它的内部緩存、系統記憶體和其他處理器的緩存的資料在總線上保持一緻。如果一個正在共享的狀态的位址被嗅探到其他處理器打算寫記憶體位址,那麼正在嗅探的處理器将使它的緩存行無效,在下次通路相同記憶體位址時,強制執行緩存行填充。
9.volatile與synchronized有什麼差別?
- volatile僅能使用在變量上,synchronized則可以使用在方法、類、同步代碼塊等等。
- volatile隻能保證可見性和有序性,不能保證原子性。而synchronized都可以保證。
- volatile不會造成線程的阻塞,而synchronized可能會造成線程的阻塞.
10.wait()和sleep()的差別?
(1)sleep()不釋放鎖,wait()釋放鎖
(2)sleep()在Thread類中聲明的,wait()在Object類中聲明
(3)sleep()是靜态方法,是Thread.sleep(); wait()是非靜态方法,必須由“同步鎖”對象調用
(4)sleep()方法導緻目前線程進入阻塞狀态後,當時間到或interrupt()醒來;wait()方法導緻目前線程進入阻塞狀态後,由notify或notifyAll()
11.樂觀鎖和悲觀鎖的了解及如何實作,有哪些實作方式?
悲觀鎖:總是假設最壞的情況,每次去拿資料的時候都認為别人會修改,是以每次在拿資料的時候都會上鎖,這樣别人想拿這個資料就會阻塞直到它拿到鎖。傳統的關系型資料庫裡邊就用到了很多這種鎖機制,比如行鎖,表鎖等,讀鎖,寫鎖等,都是在做操作之前先上鎖。再比如 Java 裡面的同步原語 synchronized 關鍵字的實作也是悲觀鎖。
樂觀鎖:顧名思義,就是很樂觀,每次去拿資料的時候都認為别人不會修改,是以不會上鎖,但是在更新的時候會判斷一下在此期間别人有沒有去更新這個資料,可以使用版本号等機制。樂觀鎖适用于多讀的應用類型,這樣可以提高吞吐量,像資料庫提供的類似于 write_condition 機制,其實都是提供的樂觀鎖。在 Java中 java.util.concurrent.atomic 包下面的原子變量類就是使用了樂觀鎖的一種實作方式 CAS 實作的。
樂觀鎖的實作方式:
1、使用版本辨別來确定讀到的資料與送出時的資料是否一緻。送出後修改版本辨別,不一緻時可以采取丢棄和再次嘗試的政策。
2、java 中的 Compare and Swap 即 CAS ,當多個線程嘗試使用 CAS 同時更新同一個變量時,隻有其中一個線程能更新變量的值,而其它線程都失敗,失敗的線程并不會被挂起,而是被告知這次競争中失敗,并可以再次嘗試。 CAS 操作中包含三個操作數 —— 需要讀寫的記憶體位置(V)、進行比較的預期原值(A)和拟寫入的新值(B)。如果記憶體位置 V 的值與預期原值 A 相比對,那麼處理器會自動将該位置值更新為新值 B。否則處理器不做任何操作。
12.什麼是可重入鎖(ReentrantLock)?
ReentrantLock重入鎖,是實作Lock接口的一個類,也是在實際程式設計中使用頻率很高的一個鎖,支援重入性,表示能夠對共享資源能夠重複加鎖,即目前線程擷取該鎖再次擷取不會被阻塞。
在java關鍵字synchronized隐式支援重入性,synchronized通過擷取自增,釋放自減的方式實作重入。與此同時,ReentrantLock還支援公平鎖和非公平鎖兩種方式。那麼,要想完完全全的弄懂ReentrantLock的話,主要也就是ReentrantLock同步語義的學習:1. 重入性的實作原理;2. 公平鎖和非公平鎖。
重入性的實作原理
要想支援重入性,就要解決兩個問題:
- 線上程擷取鎖的時候,如果已經擷取鎖的線程是目前線程的話則直接再次擷取成功;
- 由于鎖會被擷取n次,那麼隻有鎖在被釋放同樣的n次之後,該鎖才算是完全釋放成功。
ReentrantLock支援兩種鎖:公平鎖和非公平鎖
何謂公平性,是針對擷取鎖而言的,如果一個鎖是公平的,那麼鎖的擷取順序就應該符合請求上的絕對時間順序,滿足FIFO。
資料庫面試題(經常被問到)
1.索引
1.1 什麼時候用索引?
1.2 索引的分類?
MySQL索引包括普通索引、唯一索引、全文索引、單列索引、多列索引、空間索引
1.3 索引作用和優缺點?
索引就一種特殊的查詢表,資料庫的搜尋可以利用它加速對資料的檢索。
它很類似與現實生活中書的目錄,不需要查詢整本書内容就可以找到想要的資料。
索引可以是唯一的,建立索引允許指定單個列或者是多個列。
缺點是它減慢了資料錄入的速度,同時也增加了資料庫的尺寸大小
1.4 什麼情況下索引不會命中?
2.兩種存儲引擎
1).MyISAM管理非事務表。它提供高速存儲和檢索,以及全文搜尋能力。如果應用中需要執行大量的SELECT查詢,那麼MyISAM是更好的選擇。
2).InnoDB用于事務處理應用程式,具有衆多特性,包括ACID事務支援。如果應用中需要執行大量的INSERT或UPDATE操作,則應該使用InnoDB,這樣可以提高多使用者并發操作的性能。
主要差別: 1).MyISAM是非事務安全型的,而InnoDB是事務安全型的。 2).MyISAM鎖的粒度是表級,而InnoDB支援行級鎖定。 3).MyISAM支援全文類型索引,而InnoDB不支援全文索引。 4).MyISAM相對簡單,是以在效率上要優于InnoDB,小型應用可以考慮使用MyISAM。 5).MyISAM表是儲存成檔案的形式,在跨平台的資料轉移中使用MyISAM存儲會省去不少的麻煩。 6).InnoDB表比MyISAM表更安全,可以在保證資料不會丢失的情況下,切換非事務表到事務表(alter table tablename type=innodb)。
3.資料庫優化
(1)根據服務層面:配置mysql性能優化參數;
(2)從系統層面增強mysql的性能:優化資料表結構、字段類型、字段索引、分表,分庫、讀寫分離等等。
(3)從資料庫層面增強性能:優化SQL語句,合理使用字段索引。
(4)從代碼層面增強性能:使用緩存和NoSQL資料庫方式存儲,如MongoDB/Memcached/Redis來緩解高并發下資料庫查詢的壓力。
(5)減少資料庫操作次數,盡量使用資料庫通路驅動的批處理方法。
(6)不常使用的資料遷移備份,避免每次都在海量資料中去檢索。
(7)提升資料庫伺服器硬體配置,或者搭建資料庫叢集。
(8)程式設計手段防止SQL注入:使用JDBC PreparedStatement按位插入或查詢;正規表達式過濾(非法字元串過濾)
sql語句優化
1.對查詢進行優化,應盡量避免全表掃描,首先應考慮在 where 及 order by 涉 及的列上建立索引。 2.應盡量避免在 where 子句中對字段進行 null 值判斷,否則将導緻引擎放棄使 用索引而進行全表掃描,如: select id from t where num is null 可以在num上設定預設值0,確定表中num列沒有null值,然後這樣查詢: select id from t where num=0 3.應盡量避免在 where 子句中使用!=或<>操作符,否則将引擎放棄使用索引而 進行全表掃描。 4.應盡量避免在 where 子句中使用 or 來連接配接條件,否則将導緻引擎放棄使用索 引而進行全表掃描,如: select id from t where num=10 or num=20 可以這樣查詢: select id from t where num=10 union all select id from t where num=20 5.in 和 not in 也要慎用,否則會導緻全表掃描,如: select id from t where num in(1,2,3) 對于連續的數值,能用 between 就不要用 in 了: select id from t where num between 1 and 3 6.下面的查詢也将導緻全表掃描: select id from t where name like ‘%abc%’ 7.應盡量避免在 where 子句中對字段進行表達式操作,這将導緻引擎放棄使用 索引而進行全表掃描。如: select id from t where num/2=100 應改為: select id from t where num=100*2
8.應盡量避免在where子句中對字段進行函數操作,這将導緻引擎放棄使用索引 而進行全表掃描。如: select id from t where substring(name,1,3)=‘abc’–name以abc開頭的id 應改為: select id from t where name like 'abc%' 9.不要在 where 子句中的“=”左邊進行函數、算術運算或其他表達式運算, 否則系統将可能無法正确使用索引。 10.在使用索引字段作為條件時,如果該索引是複合索引,那麼必須使用到該索 引中的第一個字段作為條件時才能保證系統使用該索引, 否則該索引将不會被使用,并且應盡可能的讓字段順序與索引順序相一緻。 11.不要寫一些沒有意義的查詢,如需要生成一個空表結構: select col1,col2 into #t from t where 1=0 這類代碼不會傳回任何結果集,但是會消耗系統資源的,應改成這樣: create table #t(…) 12.很多時候用 exists 代替 in 是一個好的選擇: select num from a where num in(select num from b) 用下面的語句替換: select num from a where exists(select 1 from b where num=a.num) 13.并不是所有索引對查詢都有效,SQL是根據表中資料來進行查詢優化的,當 索引列有大量資料重複時,SQL查詢可能不會去利用索引, 如一表中有字段sex,male、female幾乎各一半,那麼即使在sex上建了索引也 對查詢效率起不了作用。 14.索引并不是越多越好,索引固然可以提高相應的 select 的效率,但同時也降 低了 insert 及 update 的效率, 因為 insert 或 update 時有可能會重建索引,是以怎樣建索引需要慎重考慮, 視具體情況而定。 一個表的索引數最好不要超過6個,若太多則應考慮一些不常使用到的列上建的 索引是否有必要。 15.盡量使用數字型字段,若隻含數值資訊的字段盡量不要設計為字元型,這會 降低查詢和連接配接的性能,并會增加存儲開銷。 這是因為引擎在處理查詢和連接配接時會逐個比較字元串中每一個字元,而對于數字 型而言隻需要比較一次就夠了。 16.盡可能的使用 varchar 代替 char ,因為首先變長字段存儲空間小,可以節 省存儲空間, 其次對于查詢來說,在一個相對較小的字段内搜尋效率顯然要高些。 17.任何地方都不要使用 select * from t ,用具體的字段清單代替“*”,不要 傳回用不到的任何字段。 18.避免頻繁建立和删除臨時表,以減少系統表資源的消耗。 19.臨時表并不是不可使用,适當地使用它們可以使某些例程更有效,例如,當 需要重複引用大型表或常用表中的某個資料集時。但是,對于一次性事件,最好 使用導出表。 20.在建立臨時表時,如果一次性插入資料量很大,那麼可以使用 select into 代 替 create table,避免造成大量 log , 以提高速度;如果資料量不大,為了緩和系統表的資源,應先create table,然 後insert。 21.如果使用到了臨時表,在存儲過程的最後務必将所有的臨時表顯式删除,先 truncate table ,然後 drop table ,這樣可以避免系統表的較長時間鎖定。 22.盡量避免使用遊标,因為遊标的效率較差,如果遊标操作的資料超過1萬行, 那麼就應該考慮改寫。 23.使用基于遊标的方法或臨時表方法之前,應先尋找基于集的解決方案來解決 問題,基于集的方法通常更有效。 24.與臨時表一樣,遊标并不是不可使用。對小型資料集使用 FAST_FORWARD 遊标通常要優于其他逐行處理方法,尤其是在必須引用幾個表才能獲得所需的數 據時。 在結果集中包括“合計”的例程通常要比使用遊标執行的速度快。如果開發時間 允許,基于遊标的方法和基于集的方法都可以嘗試一下,看哪一種方法的效果更 好。 25.盡量避免大事務操作,提高系統并發能力。 26.盡量避免向用戶端傳回大資料量,若資料量過大,應該考慮相應需求是否合 理。
4.資料庫事務
事務:是一系列的資料庫操作,是資料庫應用的基本邏輯機關。
四大特性:原子性、一緻性、隔離性、持久性
5.存儲過程
什麼是存儲過程?用什麼來調用?
存儲過程是一個預編譯的SQL語句,優點是允許子產品化的設計,就是說隻需建立一次,以後在該程式中就可以調用多次。 如果某次操作需要執行多次SQL,使用存儲過程比單純SQL語句執行要快。 調用: 1)可以用一個指令對象來調用存儲過程。 2)可以供外部程式調用,比如:java程式。
存儲過程的優缺點?
優點: 1)存儲過程是預編譯過的,執行效率高。 2)存儲過程的代碼直接存放于資料庫中,通過存儲過程名直接調用,減少網絡通訊。 3)安全性高,執行存儲過程需要有一定權限的使用者。 4)存儲過程可以重複使用,可減少資料庫開發人員的工作量。 缺點:移植性差
//建立存儲過程 CREATE PROCEDURE userData( IN id INT ) BEGIN SELECT * from userdata WHERE userflag = id; END; 其中IN是傳進去的變量; drop procedure userData;//銷毀這個存儲過程 call userData(2) //調用存儲過程
6.DDL和DML
DDL (Data Definition Language 資料定義語言)DML (Data Manipulation Language 資料操作語言)create table 建立表 alter table 修改表 drop table 删除表 truncate table 删除表中所有行 create index 建立索引 drop index 删除索引 當執行DDL語句時,在每一條語句前後,oracle都将送出目前的事務。如果使用者使用insert指令将記錄插入到資料庫後,執行了一條DDL語句(如create table),此時來自insert指令的資料将被送出到資料庫。當DDL語句執行完成時,DDL語句會被自動送出,不能復原。
insert 将記錄插入到資料庫 update 修改資料庫的記錄 delete 删除資料庫的記錄 當執行DML指令如果沒有送出,将不會被其他會話看到。除非在DML指令之後執行了DDL指令或DCL指令,或使用者退出會話,或終止執行個體,此時系統會自動發出commit指令,使未送出的DML指令送出。
7.内連接配接、左外連接配接和右外連接配接的差別?
左連接配接:左邊有的,右邊沒有的為null
右連接配接:左邊沒有的,右邊有的為null
内連接配接:顯示左邊右邊共有的
全連接配接:左連接配接和右連接配接的并集
8.資料庫的三大範式?
第一範式
資料庫表的每一列都是不可分割的基本資料項,同一列中不能有多個值,即實體中的某個屬性不能有多個值或者不能有重複的屬性。(保持資料的原子性)
第二範式
在滿足第一範式的基礎上,實體的每個非主鍵屬性完全函數依賴于主鍵屬性(消除部分依賴)
第三範式
在滿足第二範式的基礎上,在實體中不存在非主鍵屬性傳遞函數依賴于主鍵屬性。(表中字段[非主鍵]不存在對主鍵的傳遞依賴)
9.防止sql注入的方法?
1.把應用伺服器的資料庫權限降至最低
2.(簡單又有效的方法)PreparedStatement
采用預編譯語句集,它内置了處理SQL注入的能力,隻要使用它的setXXX方法傳值即可。 使用好處: (1).代碼的可讀性和可維護性. (2).PreparedStatement盡最大可能提高性能. (3).最重要的一點是極大地提高了安全性. 原理: sql注入隻對sql語句的準備(編譯)過程有破壞作用 而PreparedStatement已經準備好了,執行階段隻是把輸入串作為資料處理, 而不再對sql語句進行解析,準備,是以也就避免了sql注入問題.
3.使用正規表達式過濾傳入的參數
4.字元串過濾
5.對進入資料庫的特殊字元進行轉義處理
6.JSP頁面判斷代碼
7.使用專門的SQL 注入檢測工具測試,如sqlmap、SQLninja等
事務面試題
1.事務的7種傳播級别
1) PROPAGATION_REQUIRED ,預設的spring事務傳播級别,使用該級别的特點是,如果上下文中已經存在事務,那麼就加入到事務中執行,如果目前上下文中不存在事務,則建立事務執行。是以這個級别通常能滿足處理大多數的業務場景。
2)PROPAGATION_SUPPORTS ,從字面意思就知道,supports,支援,該傳播級别的特點是,如果上下文存在事務,則支援事務加入事務,如果沒有事務,則使用非事務的方式執行。是以說,并非所有的包在transactionTemplate.execute中的代碼都會有事務支援。這個通常是用來處理那些并非原子性的非核心業務邏輯操作。應用場景較少。
3)PROPAGATION_MANDATORY , 該級别的事務要求上下文中必須要存在事務,否則就會抛出異常!配置該方式的傳播級别是有效的控制上下文調用代碼遺漏添加事務控制的保證手段。比如一段代碼不能單獨被調用執行,但是一旦被調用,就必須有事務包含的情況,就可以使用這個傳播級别。
4)PROPAGATION_REQUIRES_NEW ,從字面即可知道,new,每次都要一個新事務,該傳播級别的特點是,每次都會建立一個事務,并且同時将上下文中的事務挂起,執行目前建立事務完成以後,上下文事務恢複再執行。
這是一個很有用的傳播級别,舉一個應用場景:現在有一個發送100個紅包的操作,在發送之前,要做一些系統的初始化、驗證、資料記錄操作,然後發送100封紅包,然後再記錄發送日志,發送日志要求100%的準确,如果日志不準确,那麼整個父事務邏輯需要復原。 怎麼處理整個業務需求呢?就是通過這個PROPAGATION_REQUIRES_NEW 級别的事務傳播控制就可以完成。發送紅包的子事務不會直接影響到父事務的送出和復原。
5)PROPAGATION_NOT_SUPPORTED ,這個也可以從字面得知,not supported ,不支援,目前級别的特點就是上下文中存在事務,則挂起事務,執行目前邏輯,結束後恢複上下文的事務。
這個級别有什麼好處?可以幫助你将事務極可能的縮小。我們知道一個事務越大,它存在的風險也就越多。是以在處理事務的過程中,要保證盡可能的縮小範圍。比如一段代碼,是每次邏輯操作都必須調用的,比如循環1000次的某個非核心業務邏輯操作。這樣的代碼如果包在事務中,勢必造成事務太大,導緻出現一些難以考慮周全的異常情況。是以這個事務這個級别的傳播級别就派上用場了。用目前級别的事務模闆抱起來就可以了。
6)PROPAGATION_NEVER ,該事務更嚴格,上面一個事務傳播級别隻是不支援而已,有事務就挂起,而PROPAGATION_NEVER傳播級别要求上下文中不能存在事務,一旦有事務,就抛出runtime異常,強制停止執行!這個級别上輩子跟事務有仇。
7)PROPAGATION_NESTED ,字面也可知道,nested,嵌套級别事務。該傳播級别特征是,如果上下文中存在事務,則嵌套事務執行,如果不存在事務,則建立事務。
2.資料隔離級别
1、Serializable (可串化讀):最嚴格的級别,事務串行執行,資源消耗最大;
2、REPEATABLE READ(可重複讀,MySQL預設隔離級别):保證了一個事務不會修改已經由另一個事務讀取但未送出(復原)的資料。避免了“髒讀取”和“不可重複讀取”的情況,但是帶來了更多的性能損失。
3、READ COMMITTED(已送出讀) :大多數主流資料庫的預設事務等級,保證了一個事務不會讀到另一個并行事務已修改但未送出的資料,避免了“髒讀取”。該級别适用于大多數系統。
4、Read Uncommitted(未送出讀) :保證了讀取過程中不會讀取到非法資料。
3.Java有幾種類型的事務?
Java事務的類型有三種:JDBC事務、JTA(Java Transaction API)事務、容器事務。
設計模式
1.設計模式分類
常見的設計模式:
單例模式、工廠模式、建造模式、觀察者模式、擴充卡模式、代理模式、裝飾模式.
2.設計模式的優點
設計模式可在多個項目中重用。
設計模式提供了一個幫助定義系統架構的解決方案。
設計模式吸收了軟體工程的經驗。
設計模式為應用程式的設計提供了透明性。
設計模式是被實踐證明切實有效的,由于它們是建立在專家軟體開發人員的知識和經驗之上的。
3.設計模式的六大原則及其含義
- 單一職責原則:一個類隻負責一個功能領域中的相應職責,或者可以定義為:就一個類而言,應該隻有一個引起它變化的原因。主要作用實作代碼高内聚,低耦合。
- 開閉原則:一個軟體實體應當對擴充開放,對修改關閉。即軟體實體應盡量在不修改原有代碼的情況下進行擴充。
- 裡氏替換原則:所有引用基類(父類)的地方必須能透明地使用其子類的對象。裡氏替換原則是實作開閉原則的方式之一
- 依賴倒置原則:抽象不應該依賴于細節,細節應當依賴于抽象。換言之,要針對接口程式設計,而不是針對實作程式設計。
- 接口隔離原則:使用多個專門的接口,而不使用單一的總接口,即用戶端不應該依賴那些它不需要的接口。
- 迪米特法則:一個軟體實體應當盡可能少地與其他實體發生互相作用。
4.常見的單例模式以及各種實作方式的優缺點,哪一種最好,手寫常見的單利模式
餓漢式:懶漢式:
- 優點:不用加鎖可以確定對象的唯一性,線程安全。
- 缺點:初始化對象會浪費不必要的資源,未實作延遲加載。
雙重檢測鎖式(Double Check Lock--DCL):
- 優點:實作了延時加載。
- 缺點:線程不安全,想實作線程安全,得加鎖(synchronized),這樣會浪費一些不必要的資源。
- 優點:資源使用率高,效率高。
- 缺點:第一次加載稍慢,由于java處理器允許亂序執行,偶爾會失敗。
5.設計模式在實際場景的應用
單例:連接配接資料庫,記錄日志
6.Spring中用到了哪些設計模式
- 工廠模式:spring中的BeanFactory就是簡單工廠模式的展現,根據傳入一個唯一的辨別來獲得bean對象,但是否是在傳入參數後建立還是傳入參數前建立這個要根據具體情況來定。
- 代理模式:Spring的AOP就是代理模式的展現。
- 單例模式:比如在建立bean的時候。
- 政策模式:spring在執行個體化對象的時候使用到了。
- 工廠方法:Spring中的FactoryBean就是典型的工廠方法模式。
- 觀察者模式:常用的地方是Listener的實作,spring中ApplicationListener就是觀察者的展現。
7.MyBatis中用到了哪些設計模式
- Builder模式,例如SqlSessionFactoryBuilder、XMLConfigBuilder、XMLMapperBuilder、XMLStatementBuilder、CacheBuilder;
- 工廠模式,例如SqlSessionFactory、ObjectFactory、MapperProxyFactory;
- 單例模式,例如ErrorContext和LogFactory;
- 代理模式,Mybatis實作的核心,比如MapperProxy、ConnectionLogger,用的jdk的動态代理;還有executor.loader包使用了cglib或者javassist達到延遲加載的效果;
- 組合模式,例如SqlNode和各個子類ChooseSqlNode等;
- 模闆方法模式,例如BaseExecutor和SimpleExecutor,還有BaseTypeHandler和所有的子類例如IntegerTypeHandler;
- 擴充卡模式,例如Log的Mybatis接口和它對jdbc、log4j等各種日志架構的适配實作;
- 裝飾者模式,例如Cache包中的cache.decorators子包中等各個裝飾者的實作;
- 疊代器模式,例如疊代器模式PropertyTokenizer;
8.動态代理
cglib,jdk
消息隊列
1.為什麼使用消息隊列?(解耦、異步、削峰)
主要解決應用耦合,異步消息,流量削鋒等問題。
可實作高性能,高可用,可伸縮和最終一緻性架構,是大型分布式系統不可缺少的中間件。
-
解耦
傳統模式:系統間耦合性太強
中間件模式:
中間件模式的優點:
将消息寫入消息隊列,需要消息的系統自己從消息隊列中訂閱,進而系統A不需要做任何修改。
-
異步
傳統模式:一些非必要的業務邏輯以同步的方式運作,太耗費時間;
中間件模式:
将消息寫入消息隊列,非必要的業務邏輯以異步的方式運作,加快相應速度
-
削峰
傳統模式:并發量大的時間,所有的請求直接怼到資料庫,造成資料庫連接配接異常
中間件模式:
2.使用了消息隊列會有什麼缺點
- 系統可用性會降低
- 考慮一緻性問題、如何保證消息不被重複消費、如何保證消息可靠性傳輸等
3.消息隊列如何選型?
特性 | ActiveMQ | RabbitMQ | RocketMQ | kafka |
---|---|---|---|---|
開發語言 | java | erlang | java | scala |
單機吞吐量 | 萬級 | 萬級 | 10萬級 | 10萬級 |
時效性 | ms級 | us級 | ms級 | ms級以内 |
可用性 | 高(主從架構) | 高(主從架構) | 非常高(分布式架構) | 非常高(分布式架構) |
功能特性 | 成熟的産品,在很多公司得到應用;有較多的文檔;各種協定支援較好 | 基于erlang開發,是以并發能力很強,性能極其好,延時很低;管理界面較豐富 | MQ功能比較完備,擴充性佳 | 隻支援主要的MQ功能,像一些消息查詢,消息回溯等功能沒有提供,畢竟是為大資料準備的,在大資料領域應用廣。 |
4.消息隊列由哪些角色組成?
- 生産者(Producer):負責産生消息。
- 消費者(Consumer):負責消費消息
消息代理(Message Broker):負責存儲消息和轉發消息兩件事情。
轉發消息分為推送和拉取兩種方式:
1. 拉取(Pull),是指 Consumer 主動從 Message Broker 擷取消息
- 推送(Push),是指 Message Broker 主動将 Consumer 感興趣的消息推送給 Consumer 。
5.消息隊列有哪些使用場景?
一般來說,有下面使用場景:其中,應用解耦、異步處理是比較核心的。
- 應用解耦
- 異步處理
- 流量削峰
- 消息通訊
- 日志處理
資料結構
1.排序算法有哪些?
插入排序,冒泡排序,選擇排序,快速排序,堆排序,歸并排序,基數排序,希爾排序等。
2.以下算法的時間複雜度
冒泡排序法 O(n^2)
插入排序法 O(n^2)
堆排序法 O(nlog2 n)
二叉樹排序法 最差O(n2)平均O(n*log2n)
快速排序法 最差O(n2)平均O(n*log2n)
希爾排序法 O(nlog n) 不穩定
3.數組和連結清單的差別
從邏輯結構
數組必須實作定于固定的長度,不能适應資料動态增減的情況,即數組的大小一旦定義就不能改變。當資料增加是,可能超過原先定義的元素的個數;當資料減少時,造成記憶體浪費;
連結清單動态進行存儲配置設定,可以适應資料動态地增減的情況,且可以友善地插入、删除資料項。
從記憶體存儲
數組從棧中配置設定空間(用new則在堆上建立),對程式員友善快速,但是***度小;
連結清單從堆中配置設定空間,***度大但是申請管理比較麻煩
從通路方式
數組在記憶體中是連續的存儲,是以可以利用下标索引進行通路;
連結清單是鍊式存儲結構,在通路元素時候隻能夠通過線性方式由前到後順序的通路,是以通路效率比數組要低。
4.解決哈希沖突的方法
哈希表(Hash table,也叫散清單),是根據關鍵碼值(Key value)而直接進行通路的資料結構。
1) 線性探測法
2) 平方探測法
3) 僞随機序列法
4) 拉鍊法
集合面試題(常見)
1.常見的集合有哪些?
Map接口和Collection接口是所有集合架構的父接口:
Map接口的實作類主要有:
HashMap、TreeMap、Hashtable、ConcurrentHashMap以及Properties等
Collection接口的子接口包括:Set接口和List接口
(1)List接口的實作類主要有:ArrayList、LinkedList、Stack以及Vector等
(2)Set接口的實作類主要有:HashSet、TreeSet、LinkedHashSet等
2.HashMap與HashTable的差別?
(1)HashMap沒有考慮同步,是線程不安全的;Hashtable使用了synchronized關鍵字,是線程安全的;
(2)HashMap允許K/V都為null;後者K/V都不允許為null;
(3)HashMap繼承自AbstractMap類;而Hashtable繼承自Dictionary類;
3.hashmap的底層原理,會不會産生哈希沖突?
當兩個不同的輸入值,根據同一散列函數計算出相同的散列值的現象,我們就把它叫做碰撞(哈希碰撞)
解決哈希沖突:
将數組和連結清單結合在一起,發揮兩者各自的優勢,使用一種叫做鍊位址法的方式可以解決哈希沖突
4.HashMap周遊?
兩種方式周遊:使用周遊;使用
EntrySet
周遊
KeySet
5.Set 周遊方法?
- 疊代周遊
Set<String> set = new HashSet<String>(); Iterator<String> it = set.iterator(); while (it.hasNext()) { String str = it.next(); System.out.println(str); }
- for循環周遊
for (String str : set) { System.out.println(str); }
6.Vector和ArrayList以及LinkedList差別和聯系,以及分别的應用場景
(1)ArrayList:底層基于數組,線程不安全,查詢和修改效率高,但是增加和删除效率低,
如果需要大量的查詢和修改則可以選擇ArrayList;
(2)LinkedList:底層雙向連結清單結構,線程不安全,查詢和修改效率低,但是增加和删除效率高,
如果需要大量的添加和删除則可以選擇LinkedList
(3)Vector:如果建立Vector時沒有指定容量,則預設容量為10,底層基于數組實作,線程是安全的,底層 采用synchronized同步方法進行加鎖,很少用
7.如果要保證ArraList線程安全,有幾種方式?
(1)自己重寫一個ArrayList集合類,根據業務一般來說,add/set/remove加鎖
(2)利用List<Object> list = Collections.synchronizedList(new ArrayList<>()); //采用synchronized加鎖
(3)new CopyOnWriteArrayList<>().add(""); //采用 ReentrantLock加鎖
8.ArrayList擴容機制是怎麼樣的
ArrayList集合大小如果建立時沒有指定,則預設為0,若已經指定集合大小,則初始值為指;
當第一次添加資料的時候,集合大小擴容為10,
第二次及其後續每次按照
int oldCapacity = elementData.length;
newCapacity = oldCapacity+(oldCapacity>>1)
9.HashSet和TreeSet的差別?
HashSet的存儲方式:哈希碼算法,加入的對象需要實作hashcode()方法,快速查找元素 TreeSet的存儲方式:按序存放,想要有序就要實作Comparable接口
不同點:
(1)HashSet由哈希表(實際上是一個HashMap執行個體)支援,不保證set的疊代順序,并允許使用null元素。
(2)基于HashMap實作,API也是對HashMap的行為進行了封裝,可參考HashMap
10.底層
Vector底層是數組。
Stack底層是Vector。
HashTable底層是鍊位址法組成的哈希表(即數組+單項連結清單組成)。
ArrayList底層是數組。
LinkedList底層是雙向連結清單。
HashMap底層與HashTable原理相同,Java 8版本以後如果同一位置哈希沖突大于8則連結清單變成紅黑樹。
LinkedHashMap底層修改自HashMap,包含一個維護插入順序的雙向連結清單。
TreeMap底層是紅黑樹。
HashSet底層是HashMap。
LinkedHashSet底層是LinkedHashMap。
TreeSet底層是TreeMap。
JVM面試題
1.記憶體模型以及分區,需要詳細到每個區放什麼。
JVM 分為堆區和棧區,還有方法區,初始化的對象放在堆裡面,引用放在棧裡面, class 類資訊常量池(static 常量和 static 變量)等放在方法區 new: 方法區:主要是存儲類資訊,常量池(static 常量和 static 變量),編譯後的代碼(位元組碼)等資料 堆:初始化的對象,成員變量 (那種非 static 的變量),所有的對象執行個體和數組都要在堆上配置設定
棧:棧的結構是棧幀組成的,調用一個方法就壓入一幀,幀上面存儲局部變量表,操作數棧,方法出口等資訊,局部變量表存放的是 8 大基礎類型加上一個應用類型,是以還是一個指向位址的指針 本地方法棧:主要為 Native 方法服務 程式計數器:記錄目前線程執行的行号
2.簡述 java 垃圾回收機制?
在 java 中,程式員是不需要顯示的去釋放一個對象的記憶體的,而是由虛拟機自行執行。在
JVM 中,有一個垃圾回收線程,它是低優先級的,在正常情況下是不會執行的,隻有在虛
拟機空閑或者目前堆記憶體不足時,才會觸發執行,掃面那些沒有被任何引用的對象,并将
它們添加到要回收的集合中,進行回收。
3.java 類加載過程?
加載驗證加載時類加載的第一個過程,在這個階段,将完成一下三件事情: 通過一個類的全限定名擷取該類的二進制流。 将該二進制流中的靜态存儲結構轉化為方法去運作時資料結構。 在記憶體中生成該類的 Class 對象,作為該類的資料通路入口。
準備驗證的目的是為了確定 Class 檔案的位元組流中的資訊不回危害到虛拟機.在該階段主要完成 以下四鐘驗證: 檔案格式驗證:驗證位元組流是否符合 Class 檔案的規範,如主次版本号是否在目前虛拟 機範圍内,常量池中的常量是否有不被支援的類型. 中繼資料驗證:對位元組碼描述的資訊進行語義分析,如這個類是否有父類,是否內建了不 被繼承的類等。 位元組碼驗證:是整個驗證過程中最複雜的一個階段,通過驗證資料流和控制流的分析, 确定程式語義是否正确,主要針對方法體的驗證。如:方法中的類型轉換是否正确,跳轉 指令是否正确等。4. 符号引用驗證:這個動作在後面的解析過程中發生,主要是為了確定解析動作能正确執 行。
解析準備階段是為類的靜态變量配置設定記憶體并将其初始化為預設值,這些記憶體都将在方法區中進 行配置設定。準備階段不配置設定類中的執行個體變量的記憶體,執行個體變量将會在對象執行個體化時随着對象 一起配置設定在 Java 堆中。 public static int value=123;*//在準備階段 value 初始值為 0 。在初始化階段才會變 * 為 123
初始化該階段主要完成符号引用到直接引用的轉換動作。解析動作并不一定在初始化動作完成之前,也有可能在初始化之後。
初始化時類加載的最後一步,前面的類加載過程,除了在加載階段使用者應用程式可以通過 自定義類加載器參與之外,其餘動作完全由虛拟機主導和控制。到了初始化階段,才真正開始執行類中定義的 Java 程式代碼。
JavaSE基礎
1. 談談對OOP的了解
(1)封裝:就是隐藏類的内部資訊,不允許外部程式直接通路,而是通過getter(擷取)和setter(設定)方 法完成,提高資料的安全性 (2)繼承:父類的基本特征和行為,子類也會有,子類也可以改變這些特征和行為。 (3)多态:就是多個對象調用同一個方法,可能會得到的是不同的結果。
- 首先面向對象是一種程式設計思想
- 萬物皆對象。我的電腦是一個對象,我的手機是一個對象等等,OOP可以了解為使用代碼來模拟現實生活
- 三大特性:封裝、繼承和多态
2.String底層使用什麼實作的?為什麼不可變?
的底層使用的是
String
數組。這個
char
數組和
char
這個類都是
String
修飾的,是以不可變。
final
3.重寫和重載
方法重載
是指同一個類中的多個方法具有相同的名字,參數的數量、類型、順序不同;
與傳回值無關
方法重寫
子類繼承父類,方法名、參數清單相同,方法體不同 子類中不能重寫父類中的final方法 子類中必須重寫父類中的abstract方法
4.==與equals()的差別
号在比較基本資料類型時比較的是值,而在比較兩個對象時比較的是兩個對象的位址值
==
方法存在于
equals()
類中,其底層依賴的是
Object
号,如果類沒有重寫
==
中的
Object
方法的類中,則調用
equals()
方法其實和使用
equals()
号的效果一樣
==
5.接口與抽象類
Java接口可以了解為一種特殊的類,裡面全部是由全局常量和公共的抽象方法所組成,是一種規範。
相同點:
(1)都不能被執行個體化
(2)接口的實作類或抽象類的子類都隻有實作了抽象方法後才能執行個體化。
不同點:
(1)意義不同:接口是功能的封裝,解決對象能幹什麼;抽象類是事物的抽象,解決對象到底是什麼。 (2)内容不同:接口中的内容隻能有:抽象方法(public abstract修飾),常量(public static final修飾),在JDK8中,接口還可以定義static靜态方法和default方法;而抽象類可以有普通類的所有内容和抽象方法。 (3)接口支援多繼承,類隻允許單繼承
servlet面試題
1.Servlet的生命周期?
加載和執行個體化、初始化、處理請求以及服務結束
Servlet被伺服器執行個體化後,容器運作其init方法,
請求到達時運作其service方法,
service方法自動派遣運作與請求對應的doXXX方法(doGet,doPost)等,
當伺服器決定将執行個體銷毀的時候調用其destroy方法
2.forward() 與redirect()的差別
forward是伺服器請求資源,伺服器直接通路目标位址的URL,把那個URL的響應内容讀取過來,然後把這些内容再發給浏覽器,其實用戶端浏覽器隻發了一次請求,是以它的位址欄中還是原來的位址,session,request參數都可以擷取。
redirect就是服務端根據邏輯,發送一個狀态碼,告訴浏覽器重新去請求那個位址,相當于用戶端浏覽器發送了兩次請求。
3.四種會話跟蹤技術
1)page否是代表與一個頁面相關的對象和屬性。一個頁面由一個編譯好的 Java servlet 類(可以帶有任何的 include 指令,但是沒有 include 動作)表示。這既包括 servlet 又包括被編譯成 servlet 的 JSP 頁面
2)request是是代表與 Web 客戶機發出的一個請求相關的對象和屬性。一個請求可能跨越多個頁面,涉及多個 Web 元件(由于 forward 指令和 include 動作的關系)
3)session是是代表與用于某個 Web 客戶機的一個使用者體驗相關的對象和屬性。一個 Web 會話可以也經常會跨越多個客戶機請求
4)application是是代表與整個 Web 應用程式相關的對象和屬性。這實質上是跨越整個 Web 應用程式,包括多個頁面、請求和會話的一個全局作用域
4.Request對象的主要方法
setAttribute(String name,Object):設定名字為name的request的參數值
getAttribute(String name):傳回由name指定的屬性值
getAttributeNames():傳回request對象所有屬性的名字集合,結果是一個枚舉的執行個體
getCookies():傳回用戶端的所有Cookie對象,結果是一個Cookie數組
getCharacterEncoding():傳回請求中的字元編碼方式
getContentLength():傳回請求的Body的長度
getHeader(String name):獲得HTTP協定定義的檔案頭資訊
getHeaders(String name):傳回指定名字的request Header的所有值,結果是一個枚舉的執行個體
getHeaderNames():傳回是以request Header的名字,結果是一個枚舉的執行個體
getInputStream():傳回請求的輸入流,用于獲得請求中的資料
getMethod():獲得用戶端向伺服器端傳送資料的方法
getParameter(String name):獲得用戶端傳送給伺服器端的有name指定的參數值
getParameterNames():獲得用戶端傳送給伺服器端的所有參數的名字,結果是一個枚舉的執行個體
getParameterValues(String name):獲得有name指定的參數的所有值
getProtocol():擷取用戶端向伺服器端傳送資料所依據的協定名稱
getQueryString():獲得查詢字元串
getRequestURI():擷取送出請求字元串的用戶端位址
getRemoteAddr():擷取用戶端的IP位址
getRemoteHost():擷取用戶端的名字
getSession([Boolean create]):傳回和請求相關Session
getServerName():擷取伺服器的名字
getServletPath():擷取用戶端所請求的腳本檔案的路徑
getServerPort():擷取伺服器的端口号
removeAttribute(String name):删除請求中的一個屬性
5.Servlet執行時一般實作哪幾個方法?
public void init(ServletConfig config)
public ServletConfig getServletConfig()
public String getServletInfo()
public void service(ServletRequest request,ServletResponse response)
public void destroy()
6.GenericServlet和HttpServlet有什麼差別?
GenericServlet是一個通用的協定無關的Servlet,它實作了Servlet和ServletConfig接口。
繼承自GenericServlet的Servlet應該要覆寫service()方法。
最後,為了開發一個能用在網頁上服務于使用HTTP協定請求的Servlet,你的Servlet必須要繼承自HttpServlet。
7.九大内置對象
• application
• page
• request
• response
• session
• exception
• out
• config
• pageContext
Linux常用指令(被問到比較少)
檢視程序指令
ps指令
-a,檢視所有
-u,以使用者(user)的格式顯示
-x, 顯示背景程序運作參數
-ef,以全格式顯示程序所有資訊,包括父程序Pid,建立人,建立時間,程序号。等等
一般項目中,我們首先要查詢一個程序,并對其進行删除會用一下指令
ps -a | grep helloworld 或
ps -ef |grep helloworld 或者其他
查詢到helloworld相關的程序,我們通過kill指令來操作該程序号删除該程序,kill -9 13492
顯示目錄和檔案的指令
Ls:用于檢視所有檔案夾的指令。
Dir:用于顯示指定檔案夾和目錄的指令 Tree: 以樹狀圖列出目錄内容
Du:顯示目錄或檔案大小
修改目錄,檔案權限和屬主及數組指令
Chmod:用于改變指定目錄或檔案的權限指令。
Chown:用于改變檔案擁有屬性的指令。
Chgrp:用于改變檔案群組的指令。
Chattr:用于設定檔案具有不可删除和修改權限。
Lsattr:用于顯示檔案或目錄的隐藏屬性。
建立和删除目錄的指令
Mkdir:用于建立目錄
Rmdir:用于删除空的目錄
Rm -f:用于删除不為空的目錄
建立和删除,重命名,複制檔案的指令
Touch:建立一個新的檔案
Vi:建立一個新的檔案
Rm:删除檔案或目錄
Mv:重命名或移動檔案的指令
Cp:複制指令
Scp:用于将本地的檔案或目錄複制到遠端伺服器
Wget:用于下載下傳ftp或http伺服器檔案到本地。
顯示檔案内容的指令
Cat:用于顯示指定檔案的全部内容
More:用分頁的形式顯示指定檔案的内容
Less:用分頁的形式顯示指定檔案的内容,差別是more和less翻頁使用的操作鍵不同。
Head:用于顯示檔案的前n行内容。
Tail:用于顯示檔案的後n行内容。
Tail -f:用于自動重新整理的顯示檔案後n行資料内容。
查找指令
Find:查找指定目錄或檔案的指令。
Whereis:查找指定的檔案源和二進制檔案和手冊等
Which:用于查詢指令或别名的位置。
Locate:快速查找系統資料庫中指定的内容。
Grep:在指定的檔案或标準輸出,标準輸入内,查找滿足條件的内容。
關機和重新開機計算機的指令
Shutdown:-r 關機後立即重新開機
-k 并不真正的關機,而隻是發出警告資訊給所有使用者
-h 關機後不重新啟動
Poweroff:用于關機和關閉電源
Init:改變系統運作級别
0級用于關閉系統
1 級用于單一使用者模式
2級用來進行多使用者使用模式(但不帶網絡功能)
3級用來進行多使用者使用模式(帶網絡全功能)
4級用來進行使用者自定義使用模式
5級表示進入x windows時的模式
6級用來重新開機系統
Reboot: 用于計算機重新開機 Halt:用于關閉計算機系統
壓縮和打包指令
Tar:用于多個檔案或目錄進行打包,但不壓縮,同時也用指令進行解包
Gzip:用于檔案進行壓縮和解壓縮指令,檔案擴充名為.gz結尾。
Gunzip:用于對gzip壓縮文檔進行解壓縮。
Bzip2:用于對檔案或目錄進行壓縮和解壓縮
Bzcat:用于顯示壓縮檔案的内容。
ComPRess/un compress: 壓縮/解壓縮.Z檔案
Zcat:檢視z或gz結尾的壓縮檔案内容。
Gzexe:壓縮可執行的檔案
Unarg:解壓縮.arj檔案
Zip/unzip:壓縮解壓縮.zip檔案
使用者操作指令
Su:切換使用者指令
Sudo:一系統管理者的身份執行指令
Passwd:用于修改使用者的密碼
改變目錄和檢視目前目錄指令
Cd:進入工作目錄
Cd ..:會退到上一級指令
Pwd:顯示目前使用者所在工作目錄位置
檔案連接配接指令
Ln:為源檔案建立一個連接配接,并不将源檔案複制一份,即占用的空間很小。
可以分為軟體連接配接和硬連結:
軟連接配接:也稱為符号連接配接,即為檔案或目錄建立一個快捷方式。
硬連結:給一個檔案取多于一個名字,放在不同目錄中,友善使用者使用。
Ln指令參數如下:
-f:在建立連接配接時,先将與目的對象同名的檔案或目錄删除。
-d:允許系統管理者硬連結自己的目錄。
-i:在删除與目的對象同名檔案或目錄時先詢問使用者。
-n:在建立軟連接配接時,将目的對象視為一般的檔案。
-s:建立軟連接配接,即符号連接配接。
-v:在連接配接之前顯示檔案或目錄名。
-b:将在連接配接時會被覆寫或删除的檔案進行備份。
其他指令
Who:顯示系統中有那些使用者在使用。
-ami 顯示目前使用者
-u:顯示使用者的動作/工作
-s:使用簡短的格式來顯示
-v:顯示程式版本
Free:檢視目前系統的記憶體使用情況
Uptime:顯示系統運作了多長時間
Ps:顯示瞬間程序的動态
Pstree:以樹狀方式顯示系統中所有的程序
Date:顯示或設定系統的日期與時間。
Last:顯示每月登陸系統的使用者資訊
Kill: 殺死一些特定的程序
Logout:退出系統
Useradd/userdel:添加使用者/删除使用者
Clear:清屏
Passwd:設定使用者密碼
vi編輯器
首先用vi指令打開一個檔案
末行模式指令:
:n,m w path/filename 儲存指定範圍文檔( n表開始行,m表結束行)
:q! 對檔案做過修改後,強制退出
:q 沒有對檔案做過修改退出
Wq或x 儲存退出
dd 删除光标所在行
: set number 顯示行号
:n 跳轉到n行
:s 替換字元串 :s/test/test2/g /g全局替換 /也可以用%代替
/ 查找字元串
網絡通信常用的指令
Arp:網絡位址顯示及控制
ftp:檔案傳輸
Lftp:檔案傳輸
Mail:發送/接收電子郵件
Mesg:允許或拒絕其他使用者向自己所用的終端發送資訊
Mutt E-mail 管理程式
Ncftp :檔案傳輸
Netstat:顯示網絡連接配接.路由表和網絡接口資訊
Pine:收發電子郵件,浏覽新聞討論區
Ping:用于檢視網絡是否連接配接通暢
Ssh:安全模式下遠端登陸
Telnet:遠端登入
Talk:與另一使用者對話
Traceroute:顯示到達某一主機所經由的路徑及所使用的時間。
Wget:從網路上自動下載下傳檔案
Write:向其它使用者終端寫資訊 Rlogin:遠端登入