java面試——2021校招提前批招銀網絡電話面試

1 Stringbuffer StringBuilder的相關性和區別?

 

String

Stringbuffter

Stringbuilder

相同

都是繼承與AbstractStringBuilder

區別

定長度的不變

會自動進行擴容工作,擴展爲原數組長度的2倍加2。

效率最小

線程安全/效率其次

線程不安全/ 效率最高

2 GC的垃圾回收算法和觸發FullGC的條件

Minor GC觸發條件:當Eden區滿時,觸發Minor GC。

Full GC觸發條件:

(1)調用System.gc時,系統建議執行Full GC,但是不必然執行

(2)老年代空間不足

(3)方法去空間不足

(4)通過Minor GC後進入老年代的平均大小大於老年代的可用內存

(5)由Eden區、From Space區向To Space區複製時,對象大小大於To Space可用內存,則把該對象轉存到老年代,且老年代的可用內存小於該對象大小

3 Spring的屬性注入方式有哪幾種

1 使用set方法注入

2 使用有參數構造注入

3注入對象類型屬性(重點)

 4註解注入屬性(對象也是)

5 注入複雜類型屬性

1 數組  2 list集合  3 map集合  4 properties類型

4設計的模式那些 適配器模式的是什麼?

工廠模式:BeanFactory就是簡單工廠模式的體現,用來創建對象的實例;

單例模式:Bean默認爲單例模式。

代理模式:Spring的AOP功能用到了JDK的動態代理和CGLIB字節碼生成技術;

模板方法:用來解決代碼重複的問題。比如. RestTemplate, JmsTemplate, JpaTemplate。

觀察者模式:定義對象鍵一種一對多的依賴關係,當一個對象的狀態發生改變時,所有依賴於它的對象都會得到通知被制動更新,如Spring中listener的實現–ApplicationListener。

即Adapter模式使得原本由於接口不兼容而不能一起工作的那些類可以在一起工作。

 模式中的角色

  3.1 目標接口(Target):客戶所期待的接口。目標可以是具體的或抽象的類,也可以是接口。

  3.2 需要適配的類(Adaptee):需要適配的類或適配者類。

  3.3 適配器(Adapter):通過包裝一個需要適配的對象,把原接口轉換成目標接口

 實現方式

   (1)類的適配器模式(採用繼承實現)

     (2)對象適配器(採用對象組合方式實現)

// 已存在的、具有特殊功能、但不符合我們既有的標準接口的類
class Adaptee {
	public void specificRequest() {
		System.out.println("被適配類具有 特殊功能...");
	}
}
 
// 目標接口,或稱爲標準接口
interface Target {
	public void request();
}
 
// 具體目標類,只提供普通功能
class ConcreteTarget implements Target {
	public void request() {
		System.out.println("普通類 具有 普通功能...");
	}
}
 
// 適配器類,繼承了被適配類,同時實現標準接口
class Adapter extends Adaptee implements Target{
	public void request() {
		super.specificRequest();
	}
}
 
// 測試類public class Client {
	public static void main(String[] args) {
		// 使用普通功能類
		Target concreteTarget = new ConcreteTarget();
		concreteTarget.request();
		
		// 使用特殊功能類,即適配類
		Target adapter = new Adapter();
		adapter.request();
	}
}

上面這種實現的適配器稱爲類適配器,因爲 Adapter 類既繼承了 Adaptee (被適配類),也實現了 Target 接口(因爲 Java 不支持多繼承,所以這樣來實現),在 Client 類中我們可以根據需要選擇並創建任一種符合需求的子類,來實現具體功能。另外一種適配器模式是對象適配器,它不是使用多繼承或繼承再實現的方式,而是使用直接關聯,或者稱爲委託的方式,類圖如下:

5 Redis的持久化的方式有幾種

redis提供兩種方式進行持久化,一種是RDB持久化(原理是將Reids在內存中的數據庫記錄定時 dump到磁盤上的RDB持久化),另外一種是AOF(append only file)持久化(原理是將Reids的操作日誌以追加的方式寫入文件)

RDB持久化是指在指定的時間間隔內將內存中的數據集快照寫入磁盤,實際操作過程是fork一個子進程,先將數據集寫入臨時文件,寫入成功後,再替換之前的文件,用二進制壓縮存儲

AOF持久化以日誌的形式記錄服務器所處理的每一個寫、刪除操作,查詢操作不會記錄,以文本的方式記錄,可以打開文件看到詳細的操作記錄。

 

AOF

RDB

優點

1AOF 可以更好的保護數據不丟失,一般 AOF 會每隔 1 秒,通過一個後臺線程執行一次fsync操作,最多丟失 1 秒鐘的數據

2AOF 日誌文件以 append-only 模式寫入,所以沒有任何磁盤尋址的開銷,寫入性能非常高,而且文件不容易破損,即使文件尾部破損,也很容易修復。

3AOF 日誌文件即使過大的時候,出現後臺重寫操作,也不會影響客戶端的讀寫.

4AOF 日誌文件的命令通過非常可讀的方式進行記錄,這個特性非常適合做災難性的誤刪除的緊急恢復。

1RDB 會生成多個數據文件,每個數據文件都代表了某一個時刻中 redis 的數據,這種多個數據文件的方式,非常適合做冷備,可以將這種完整的數據文件發送到一些遠程的安全存儲上去

2RDB 對 redis 對外提供的讀寫服務,影響非常小,可以讓 redis 保持高性能

3相對於 AOF 持久化機制來說,直接基於 RDB 數據文件來重啓和恢復 redis 進程,更加快速。

缺點

1對於同一份數據來說,AOF 日誌文件通常比 RDB 數據快照文件更大

2AOF 開啓後,支持的寫 QPS 會比 RDB 支持的寫 QPS 低AOF 這種較爲複雜的基於命令日誌 / merge / 回放的方式,比基於 RDB 每次持久化一份完整的數據快照文件的方式

1如果想要在 redis 故障時,儘可能少的丟失數據,那麼 RDB 沒有 AOF 好

2RDB 每次在 fork 子進程來執行 RDB 快照數據文件生成的時候,如果數據文件特別大,可能會導致對客戶端提供的服務暫停數毫秒,或者甚至數秒。

6 SpringBean的作用域有幾種

Spring框架支持以下五種bean的作用域:

    singleton : bean在每個Spring ioc 容器中只有一個實例。

    prototype:一個bean的定義可以有多個實例。

    request:每次http請求都會創建一個bean,該作用域僅在基於web的Spring ApplicationContext情形下有效。

    session:在一個HTTP Session中,一個bean定義對應一個實例。該作用域僅在基於web的Spring ApplicationContext情形下有效。

    global-session:在一個全局的HTTP Session中,一個bean定義對應一個實例。該作用域僅在基於web的Spring Application Context情形下有效。

注意: 缺省的Spring bean 的作用域是Singleton。使用 prototype 作用域需要慎重的思考,因爲頻繁創建和銷燬 bean 會帶來很大的性能開銷。

7 數據庫的索引和區別?

8springboot2.0的默認連接池是什麼?其他的連接池是什麼?

配置默認數據庫連接池(Hikari)

9Spring中的bean在多線程時候是安全的嗎?然後怎麼保證他是安全的?

結論: 不是線程安全的。Spring容器中的Bean是否線程安全,容器本身並沒有提供Bean的線程安全策略,因此可以說Spring容器中的Bean本身不具備線程安全的特性,但是具體還是要結合具體scope的Bean去研究。

Spring 的 bean 作用域(scope)類型、

     1、singleton:單例,默認作用域。

  2、prototype:原型,每次創建一個新對象。

  3、request:請求,每次Http請求創建一個新對象,適用於WebApplicationContext環境下。

  4、session:會話,同一個會話共享一個實例,不同會話使用不用的實例。

  5、global-session:全局會話,所有會話共享一個實例。

線程安全這個問題,要從單例與原型Bean分別進行說明。

Spring中的Bean默認是單例模式的,框架並沒有對bean進行多線程的封裝處理。實際上大部分時間Bean是無狀態的(比如Dao) 所以說在某種程度上來說Bean其實是安全的。但是如果Bean是有狀態的 那就需要開發人員自己來進行線程安全的保證,最簡單的辦法就是改變bean的作用域 把 "singleton"改爲’‘protopyte’ 這樣每次請求Bean就相當於是 new Bean() 這樣就可以保證線程的安全了。 有狀態就是有數據存儲功能  無狀態就是不會保存數據。

controller、service和dao層本身並不是線程安全的,只是如果只是調用裏面的方法,而且多線程調用一個實例的方法,會在內存中複製變量,這是自己的線程的工作內存,是安全的。

 關於Spring的@Controller @Service等的線程安全問題

首先問@Controller @Service是不是線程安全的?
答:默認配置下不是的。爲啥呢?因爲默認情況下@Controller沒有加上@Scope,沒有加@Scope就是默認值singleton,單例的。意思就是系統只會初始化一次Controller容器,所以每次請求的都是同一個Controller容器,當然是非線程安全的。

@RestController
public class TestController {
    private int var = 0;

    @GetMapping(value = "/test_var")
    public String test() {
        System.out.println("普通變量var:" + (++var));
        return "普通變量var:" + var ;
    }
}
----------------------------------------------------------------------
在postman裏面發三次請求,結果如下:

普通變量var:1
普通變量var:2
普通變量var:3

 說明他不是線程安全的。怎麼辦呢?可以給他加上上面說的@Scope註解,如下:

@RestController
@Scope(value = "prototype") // 加上@Scope註解,他有2個取值:單例-singleton 多實例-prototype
public class TestController {

    private int var = 0;
    
    @GetMapping(value = "/test_var")
    public String test() {
        System.out.println("普通變量var:" + (++var));
        return "普通變量var:" + var ;
    }
}

 這樣一來,每個請求都單獨創建一個Controller容器,所以各個請求之間是線程安全的,三次請求結果:

普通變量var:1
普通變量var:1
普通變量var:1

加了@Scope註解多的實例prototype是不是一定就是線程安全的呢? 

@RestController
@Scope(value = "prototype") // 加上@Scope註解,他有2個取值:單例-singleton 多實例-prototype
public class TestController {
    private int var = 0;
    private static int staticVar = 0;

    @GetMapping(value = "/test_var")
    public String test() {
        System.out.println("普通變量var:" + (++var)+ "---靜態變量staticVar:" + (++staticVar));
        return "普通變量var:" + var + "靜態變量staticVar:" + staticVar;
    }
}

----------------------------------------------------------------------------------------
普通變量var:1---靜態變量staticVar:1
普通變量var:1---靜態變量staticVar:2
普通變量var:1---靜態變量staticVar:3

雖然每次都是單獨創建一個Controller但是扛不住他變量本身是static的呀,所以說呢,即便是加上@Scope註解也不一定能保證Controller 100%的線程安全。所以是否線程安全在於怎樣去定義變量以及Controller的配置。所以來個全乎一點的實驗,代碼如

@RestController
@Scope(value = "singleton") // prototype singleton
public class TestController {

    private int var = 0; // 定義一個普通變量

    private static int staticVar = 0; // 定義一個靜態變量

    @Value("${test-int}")
    private int testInt; // 從配置文件中讀取變量

    ThreadLocal<Integer> tl = new ThreadLocal<>(); // 用ThreadLocal來封裝變量

    @Autowired
    private User user; // 注入一個對象來封裝變量

    @GetMapping(value = "/test_var")
    public String test() {
        tl.set(1);
        System.out.println("先取一下user對象中的值:"+user.getAge()+"===再取一下hashCode:"+user.hashCode());
        user.setAge(1);
        System.out.println("普通變量var:" + (++var) + "===靜態變量staticVar:" + (++staticVar) + "===配置變量testInt:" + (++testInt)
                + "===ThreadLocal變量tl:" + tl.get()+"===注入變量user:" + user.getAge());
        return "普通變量var:" + var + ",靜態變量staticVar:" + staticVar + ",配置讀取變量testInt:" + testInt + ",ThreadLocal變量tl:"
                + tl.get() + "注入變量user:" + user.getAge();
    }
}

1、在@Controller/@Service等容器中,默認情況下,scope值是單例-singleton的,也是線程不安全的。
2、儘量不要在@Controller/@Service等容器中定義靜態變量,不論是單例(singleton)還是多實例(prototype)他都是線程不安全
3、默認注入的Bean對象,在不設置scope的時候他也是線程不安全的。
4、一定要定義變量的話,用ThreadLocal來封裝,這個是線程安全的。

10redis是怎麼樣實現的分佈式鎖的?原理是什麼?還有什麼可以實現分佈式的鎖?

 

11、集合有哪些?

12、HashMap底層源碼一問到底,數據結構,put,擴容等等,爲啥用紅黑樹?二叉搜索樹不行麼;

JDK1.7數組+鏈表             分段鎖機制      頭部插入法  多線程的時候產生 鏈表閉環

JDk1.8數組+鏈表+紅黑樹  CAS+node +synchronize鎖機制     尾部插入法 數據可能丟失。

當元素個數大於3/4的時候採取的是擴容的操作。鏈表的個數大於8個的時候將採用的紅黑樹的結構來實現。

原因的AVL樹和紅黑樹有幾點比較和區別:
(1)AVL樹是更加嚴格的平衡,因此可以提供更快的查找速度,一般讀取查找密集型任務,適用AVL樹。
(2)紅黑樹更適合於插入修改密集型任務。
(3)通常,AVL樹的旋轉比紅黑樹的旋轉更加難以平衡和調試。

在CurrentHashMap中是加鎖了的,實際上是讀寫鎖,如果寫衝突就會等待,如果插入時間過長必然等待時間更長,而紅黑樹相對AVL樹他的插入更快!

13、ConcurrentHashMap在1.8中的底層,CAS原理,用啥鎖,以及它在JDK1.7中的底層;

 

14、SQL索引,及其添加索引和判斷是否添加成功;

 

15、事務的特性。

 原子性 一致性  持久性  隔離性

16.String、StringBuffer、StringBuilder區別。

 

String

Stringbuffter

Stringbuilder

相同

都是繼承與AbstractStringBuilder

區別

定長度的不變

會自動進行擴容工作,擴展爲原數組長度的2倍加2。

效率最小

線程安全/效率其次

線程不安全/ 效率最高

17.普通類和抽象類區別。

抽象類不能被實例化  但是普通類是可以實例化的

抽象類可以有抽象方法,抽象方法只需申明,無需實現

含有抽象方法的類必須申明爲抽象類 但是的普通類是可以的

抽象類的子類必須實現抽象類中所有抽象方法,否則這個子類也是抽象類 但是的普通類是可以的

抽象方法不能被聲明爲靜態 但是的普通類是可以的

抽象方法不能用 private 修飾  但是的普通類是可以的

抽象方法不能用 final 修飾   但是普通類是可以用 final

18.session和cookie區別。

session:是一種將會話狀態保存在服務器端的技術。Cookie是一種在瀏覽器的技術。

Cookie :Web 服務器保存在用戶瀏覽器(客戶端)上的小文本文件,它可以包含有關用戶的信息。無論何時用戶鏈接到服Web 站點都可以訪問 Cookie信息 。

存儲位置不同:session 存儲在服務器端;cookie 存儲在瀏覽器端。

安全性不同:cookie 安全性一般,在瀏覽器存儲,可以被僞造和修改。

容量和個數限制:cookie 有容量限制,每個站點下的 cookie 也有個數限制。

存儲的多樣性:session 可以存儲在 Redis 中、數據庫中、應用程序中;而 cookie只能存儲在瀏覽器中。

session 的工作原理是客戶端登錄完成之後,服務器會創建對應的 session,session 創建完之後,會把 session 的 id 發送給客戶端,客戶端再存儲到瀏覽器中。這樣客戶端每次訪問服務器時,都會帶sessionid,服務器拿到 sessionid 之後,在內存找到與之對應的 session 這樣就可以正常工作了。session 只是依賴cookie存儲 sessionid,如果cookie 被禁用了,可以使用 url 中添加sessionid 的方式保證 session 能正常使用。

19.集合體系

20Spring的特性有什麼?

衆所周知,Spring的核心特性就是IOC和AOP。

SpringIOC 是spring提供對類的全生命週期的一個管理,通過利用springIOC容器來實現bean的實例化創建和銷燬。IOC容器獲取對象是程序在加載xml配置文件時通過反射調用構造函數來創建對象(我們開始學就是在xml裏配置的),將類的創建和依賴關係寫在配置文件裏,由配置文件注入,實現了松耦。

AOP 是一種編程思想。是面向切面編程的一種思想,在傳統的架構中都是垂直的流程體系。但是在這個過程中經常產生一些橫向問題,比如log日誌記錄,權限驗證,事務處理,性能檢查的問題,爲了遵循軟件的開閉原則。就是對原來不修改進而擴展原方法和原類的功能。SpringAOP就是實現了這樣一種思想。通過對原方法和類在不修改代碼的情況下而進行了類的增強的方式。主要是通過使用的動態代理技術來實現。

21抽象和接口的區別?

抽象類和接口的區別:一個類只能繼承一個抽象類,而一個類卻可以實現多個接口。(單繼承多實現方式)

 

接口

抽象類

相同點

接口和抽象類都不能被實例化,它們都位於繼承樹的頂端,用於被其他類實現和繼承。實現接口或繼承抽象類的普通子類都必須實現這些抽象方法

不同點

1只能包含抽象方法,靜態方法和默認方法,不能爲普通方法提供方法實現(但是在JDK1.8以後可以使用default和static關鍵字來修飾接口中定義的普通方法)

2接口中的成員變量只能是 public static final 類型的

3接口不能包含構造器

4接口裏不能包含初始化塊

1完全可以包含普通方法,接口中的普通方法默認爲抽象方法

2抽象類中的成員變量可以是各種類型的

3抽象類可以包含構造器,抽象類裏的構造器並不是用於創建對象,而是讓其子類調用這些構造器來完成屬於抽象類的初始化操作。

4抽象類裏完全可以包含初始化塊。

22多線程的理解

23sleep()和wait()的區別?

24HashMap和HashTable的區別  是什麼哪一個用的多?爲什麼?

歸結起來就兩點:

第一、是否爲null。HashMap允許key,value爲null,而HashTable不允許。

第二、是否線程安全。HashMap爲非線程安全的,適用於單線程,而HashTable線程安全,適用於多線程。

25 SSM的框架的理解?

SpringMVC Spring Mybatis   組成的相關的

26線程的創建和線程的狀態?

27線程的隔離機制和和區別?

28 如果打開一個網站慢了是什麼原因?

1. 當網站訪問較慢時,首先先查看本地網絡是否正常。

方法:先用網絡測速測下本地的網絡速率:網絡速率低於50KB/s,訪問網站自然也慢。

2. 本地網絡速率正常時,再檢查下所訪問的網站是否正常。

方法:測一下網站的訪問性能操作:在網站檢測中,輸入IP或域名,選擇單文件或全頁面進行測試,

分析報告: DNS服務器:顯示訪問者的出口DNS,作用是通過出口DNS獲取訪問者所在的網絡,如:xx.xx.xx.xx(北京 網通)網站解析IP:網頁的IP地址,作用獲悉IP地址,可使用ping命令檢查該IP的連通性,診斷該網站是否正常,如ping網頁時丟包較嚴重,訪問速率也會越低

總時間:網站的響應時間,可瞭解網站的性能瓶頸或者是利用谷歌或IE瀏覽器的F12開發者工具查看下網站的大小和網站的打開速度成不成正比。

3. 網站出現無法訪問時,使用故障診斷命令定位故障點。

命令分析: ping:檢測IP或域名的連通性 dig/nslookup:查看DNS解

析情況 traceroute:顯示從訪問者到網站的路由連接狀態,如果有節點無法連接,需針對該故障點進行修復便可快速恢復網絡。

29 說一下觀察者模式,說一個應用到的業務背景

 

30 SQL注入

#{}和${}的區別:SQL的防注入。預防 SQL 注入攻擊的方法

    嚴格限制 Web 應用的數據庫的操作權限,給連接數據庫的用戶提供滿足需要的最低權限,最大限度的減少注入攻擊對數據庫的危害

    校驗參數的數據格式是否合法(可以使用正則或特殊字符的判斷)

    對進入數據庫的特殊字符進行轉義處理,或編碼轉換

    預編譯SQL(Java 中使用 PreparedStatement),參數化查詢方式,避免 SQL 拼接

    發佈前,利用工具進行 SQL 注入檢測

    報錯信息不要包含 SQL 信息輸出到 Web 頁面Spring

31 如何創建線程池。 線程有哪些狀態?具體解釋一下阻塞狀態。調用了start方***進入什麼狀態?

1、新建狀態(New):新創建了一個線程對象。

2、就緒狀態(Runnable):線程對象創建後,其他線程調用了該對象的start()方法。該狀態的線程位於可運行線程池中,變得可運行,等待獲取CPU的使用權。

3、運行狀態(Running):就緒狀態的線程獲取了CPU,執行程序代碼。

4、阻塞狀態(Blocked):阻塞狀態是線程因爲某種原因放棄CPU使用權,暫時停止運行。直到線程進入就緒狀態,纔有機會轉到運行狀態。阻塞的情況分三種:

(一)、等待阻塞:運行的線程執行wait()方法,JVM會把該線程放入等待池中。(wait會釋放持有的鎖)

(二)、同步阻塞:運行的線程在獲取對象的同步鎖時,若該同步鎖被別的線程佔用,則JVM會把該線程放入鎖池中。

(三)、其他阻塞:運行的線程執行sleep()或join()方法,或者發出了I/O請求時,JVM會把該線程置爲阻塞狀態。當sleep()狀態超時、join()等待線程終止或者超時、或者I/O處理完畢時,線程重新轉入就緒狀態。(注意,sleep是不會釋放持有的鎖)

5、死亡狀態(Dead):線程執行完了或者因異常退出了run()方法,該線程結束生命週期。

新建線程對象後,調用該線程的 start()方法就可以啓動線程。當線程啓動時,線程進入就緒狀態(runnable)。由於還沒有分配CPU,線程將進入線程隊列排隊,等待 CPU 服務,這表明它已經具備了運行條件。當系統挑選一個等待執行的Thread對象後,它就會從等待執行狀態進入執行狀態。系統挑選的動作稱之爲“CPU調度"。一旦獲得CPU線程就進入運行狀態並自動調用自己的run方法。

32 我設計索引  explain關鍵字

 

33  寫過socket套接字嗎,寫一個例子

 

34 項目中用戶模塊從收到http請求到響應的全過程

 

35  get和post的區別

36 如何用兩個棧構建隊列

class CQueue {
    Deque<Integer> stack1;
    Deque<Integer> stack2;
    public CQueue() {
        stack1 = new LinkedList<Integer>();
        stack2 = new LinkedList<Integer>();
    }
    public void appendTail(int value) {
        stack1.push(value);
    }
    public int deleteHead() {
        // 如果第二個棧爲空
        if (stack2.isEmpty()) {
            //將棧1的數據放入到棧2中
            while (!stack1.isEmpty()) {
                stack2.push(stack1.pop());
            }
        } 
        if (stack2.isEmpty()) {
            return -1;
        } else {
            //如果是棧中不爲空的話就彈出
            int deleteItem = stack2.pop();
            return deleteItem;
        }
    }
}

37重寫與重載的區別,可以重寫父類的構造函數嗎;

重寫是對方法內部的重寫,而重載是的函數的返回值或者形參個數 參數類型的不同的不修改方法內部本身。

方法重載是讓類以統一的方式處理不同類型數據的一種手段。多個同名函數同時存在,具有不同的參數個數/類型。重載Overloading是一個類中多態性的一種表現。

Java的方法重載,就是在類中可以創建多個方法,它們具有相同的名字,但具有不同的參數和不同的定義。

重載的時候,方法名要一樣,但是參數類型和個數不一樣,返回值類型可以相同也可以不相同。無法以返回型別作爲重載函數的區分標準。

父類與子類之間的多態性,對父類的函數進行重新定義。如果在子類中定義某方法與其父類有相同的名稱和參數,我們說該方法被重寫 (Overriding)。在Java中,子類可繼承父類中的方法,而不需要重新編寫相同的方法。但有時子類並不想原封不動地繼承父類的方法,而是想作一定的修改,這就需要採用方法的重寫。方法重寫又稱方法覆蓋。

若子類中的方法與父類中的某一方法具有相同的方法名、返回類型和參數表,則新方法將覆蓋原有的方法。如需父類中原有的方法,可使用super關鍵字,該關鍵字引用了當前類的父類。

38 String可以被繼承嗎?

不能被繼承,因爲String類有final修飾符,而final修飾的類是不能被繼承的。

39 線程創建方式,callable和其他兩種的創建方式有什麼不一樣?

一共有以下三種方式:
1.繼承Thread
2.實現Runnable
3.實現Callable,並FutureTask包裝

 Runnable和Callable的異同:

相同點:

       兩者都是接口;(廢話)

       兩者都可用來編寫多線程程序;

       兩者都需要調用Thread.start()啓動線程;

不同點:

       兩者最大的不同點是:實現Callable接口的任務線程能返回執行結果;而實現Runnable接口的任務線程不能返回結果;

       Callable接口的call()方法允許拋出異常;而Runnable接口的run()方法的異常只能在內部消化,不能繼續上拋;

注意點:Callable接口支持返回執行結果,此時需要調用FutureTask.get()方法實現,此方法會阻塞主線程直到獲取‘將來’結果;當不調用此方法時,主線程不會阻塞!

Callable的優勢

  多線程返回執行結果是很有用的一個特性,因爲多線程相比單線程更難、更復雜的一個重要原因就是因爲多線程充滿着未知性,某條線程是否執行了?某條線程執行了多久?某條線程執行的時候我們期望的數據是否已經賦值完畢?無法得知,我們能做的只是等待這條多線程的任務執行完畢而已。而Callable+Future/FutureTask卻可以獲取多線程運行的結果,可以在等待時間太長沒獲取到需要的數據的情況下取消該線程的任務,真的是非常有用。

40 垃圾回收算法,可達性分析算法GCroots是哪些對象?

虛擬機棧中引用的對象、方法區類靜態屬性引用的對象、方法區常量池引用的對象、本地方法棧JNI引用的對象

41 tcp的擁塞控制,窗口具體是怎麼變化的?

42 索引失效的情況有哪些?

1.有or必全有索引;

2.複合索引未用左列字段;

3.like以%開頭;

4.需要類型轉換;

5.where中索引列有運算;

6.where中索引列使用了函數;

7.如果mysql覺得全表掃描更快時(數據少);

什麼時沒必要用

1.唯一性差;

2.頻繁更新的字段不用(更新索引消耗);

3.where中不用的字段;

4.索引使用<>時,效果一般;

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章