<th id="l0kf1"></th>

<dd id="l0kf1"><center id="l0kf1"></center></dd>

    1. <span id="l0kf1"></span>
    2. 更多課程 選擇中心
      Java培訓

      400-111-8989

      2021年Java面試題目及答案匯總-多線程

      • 發布:Java培訓
      • 來源:Java面試題
      • 時間:2021-02-24 14:35

      2021年Java面試題目及答案匯總-多線程。針對目前求職旺季,很多參加完Java培訓后面試過程中常常被“考問住”下面小編針對Java程序員多線程面試題目做詳細的解答,希望對于面試的小伙伴有所幫助。

      1、什么是進程?

      進程是系統中正在運行的一個程序,程序一旦運行就是進程。

      進程可以看成程序執行的一個實例。進程是系統資源分配的獨立實體,每個進程都擁有獨立的地址空間。一個進程無法訪問另一個進程的變量和數據結構,如果想讓一個進程訪問另一個進程的資源,需要使用進程間通信,比如管道,文件,套接字等。

      2、什么是線程?

      是操作系統能夠進行運算調度的最小單位。它被包含在進程之中,是進程中的實際運作單位。一條線程指的是進程中一個單一順序的控制流,一個進程中可以并發多個線程,每條線程并行執行不同的任務。

      3、線程的實現方式?

      1)繼承Thread類

      2)實現Runnable接口

      3)使用Callable和Future

      4、Thread 類中的start() 和 run() 方法有什么區別?

      1)start()方法來啟動線程,真正實現了多線程運行。這時無需等待run方法體代碼執行完畢,可以直接繼續執行下面的代碼;通過調用Thread類的start()方法來啟動一個線程, 這時此線程是處于就緒狀態, 并沒有運行。然后通過此Thread類調用方法run()來完成其運行操作的, 這里方法run()稱為線程體,它包含了要執行的這個線程的內容, Run方法運行結束, 此線程終止。然后CPU再調度其它線程。

      2)run()方法當作普通方法的方式調用。程序還是要順序執行,要等待run方法體執行完畢后,才可繼續執行下面的代碼;程序中只有主線程——這一個線程, 其程序執行路徑還是只有一條, 這樣就沒有達到寫線程的目的。

      5、線程NEW狀態

      new創建一個Thread對象時,并沒處于執行狀態,因為沒有調用start方法啟動改線程,那么此時的狀態就是新建狀態。

      6、線程RUNNABLE狀態

      線程對象通過start方法進入runnable狀態,啟動的線程不一定會立即得到執行,線程的運行與否要看cpu的調度,我們把這個中間狀態叫可執行狀態(RUNNABLE)。

      7、線程的RUNNING狀態

      一旦cpu通過輪詢貨其他方式從任務可以執行隊列中選中了線程,此時它才能真正的執行自己的邏輯代碼。

      8、線程的BLOCKED狀態

      線程正在等待獲取鎖。

      進入BLOCKED狀態,比如調用了sleep,或者wait方法

      進行某個阻塞的io操作,比如因網絡數據的讀寫進入BLOCKED狀態

      獲取某個鎖資源,從而加入到該鎖的阻塞隊列中而進入BLOCKED狀態

      9、線程的TERMINATED狀態

      TERMINATED是一個線程的最終狀態,在該狀態下線程不會再切換到其他任何狀態了,代表整個生命周期都結束了。

      下面幾種情況會進入TERMINATED狀態:

      線程運行正常結束,結束生命周期

      線程運行出錯意外結束

      JVM Crash 導致所有的線程都結束

      10、線程狀態轉化圖

      線程狀態轉化圖

      11、i–與System.out.println()的異常

      示例代碼:

      i–與System.out.println()的異常

      結果:

      i–與System.out.println()的異常

      雖然println()方法在內部是同步的,但i——————的操作卻是在進入println()之前發生的,所以有發生非線程安全的概率。

      println()源碼:

      i–與System.out.println()的異常

      12、如何知道代碼段被哪個線程調用?

      System.out.println(Thread.currentThread().getName());

      13、線程活動狀態?

      線程活動狀態

      14、sleep()方法

      方法sleep()的作用是在指定的毫秒數內讓當前的“正在執行的線程”休眠(暫停執行)。

      15、如何優雅的設置睡眠時間?

      jdk1.5 后,引入了一個枚舉TimeUnit,對sleep方法提供了很好的封裝。

      比如要表達2小時22分55秒899毫秒。

      Thread.sleep(8575899L);TimeUnit.HOURS.sleep(3);TimeUnit.MINUTES.sleep(22);TimeUnit.SECONDS.sleep(55);TimeUnit.MILLISECONDS.sleep(899);

      可以看到表達的含義更清晰,更優雅。

      16、停止線程

      run方法執行完成,自然終止。

      stop()方法,suspend()以及resume()都是過期作廢方法,使用它們結果不可預期。

      大多數停止一個線程的操作使用Thread.interrupt()等于說給線程打一個停止的標記, 此方法不回去終止一個正在運行的線程,需要加入一個判斷才能可以完成線程的停止。

      17、interrupted 和 isInterrupted

      interrupted : 判斷當前線程是否已經中斷,會清除狀態。

      isInterrupted :判斷線程是否已經中斷,不會清除狀態。

      18、yield

      放棄當前cpu資源,將它讓給其他的任務占用cpu執行時間。但放棄的時間不確定,有可能剛剛放棄,馬上又獲得cpu時間片。

      測試代碼:(cpu獨占時間片)

      yield

      結果:

      用時 = 20 毫秒!

      加入yield,再來測試。(cpu讓給其他資源導致速度變慢)

      Java多線程面試題目答案

      結果:

      用時 = 38424 毫秒!

      19、線程的優先級

      在操作系統中,線程可以劃分優先級,優先級較高的線程得到cpu資源比較多,也就是cpu有限執行優先級較高的線程對象中的任務,但是不能保證一定優先級高,就先執行。

      Java的優先級分為1~10個等級,數字越大優先級越高,默認優先級大小為5。超出范圍則拋出:java.lang.IllegalArgumentException。

      20、優先級繼承特性

      線程的優先級具有繼承性,比如a線程啟動b線程,b線程與a優先級是一樣的。

      21、誰跑的更快?

      設置優先級高低兩個線程,累加數字,看誰跑的快,上代碼。

      Java多線程題目

      Java多線程題目

      結果:

      low = 1193854568high = 1204372373

      22、線程種類

      Java線程有兩種,一種是用戶線程,一種是守護線程。

      23、守護線程的特點

      守護線程是一個比較特殊的線程,主要被用做程序中后臺調度以及支持性工作。當Java虛擬機中不存在非守護線程時,守護線程才會隨著JVM一同結束工作。

      24、Java中典型的守護線程

      GC(垃圾回收器)

      25、如何設置守護線程

      Thread.setDaemon(true)

      PS:Daemon屬性需要再啟動線程之前設置,不能再啟動后設置。

      26、Java虛擬機退出時Daemon線程中的finally塊一定會執行?

      Java虛擬機退出時Daemon線程中的finally塊并不一定會執行。

      代碼示例:

      結果:

      沒有任何的輸出,說明沒有執行finally。

      27、設置線程上下文類加載器

      獲取線程上下文類加載器

      public ClassLoader getContextClassLoader()

      設置線程類加載器(可以打破Java類加載器的父類委托機制)

      public void setContextClassLoader(ClassLoader cl)

      28、join

      join是指把指定的線程加入到當前線程,比如join某個線程a,會讓當前線程b進入等待,直到a的生命周期結束,此期間b線程是處于blocked狀態。

      29、什么是synchronized?

      synchronized關鍵字可以時間一個簡單的策略來防止線程干擾和內存一致性錯誤,如果一個對象是對多個線程可見的,那么對該對想的所有讀寫都將通過同步的方式來進行。

      30、synchronized包括哪兩個jvm重要的指令?

      monitor enter 和 monitor exit

      31、synchronized關鍵字用法?

      可以用于對代碼塊或方法的修飾

      32、synchronized鎖的是什么?

      普通同步方法 —————> 鎖的是當前實力對象。

      靜態同步方法—————> 鎖的是當前類的Class對象。

      同步方法快 —————> 鎖的是synchonized括號里配置的對象。

      33、Java對象頭

      synchronized用的鎖是存在Java對象頭里的。對象如果是數組類型,虛擬機用3個字寬(Word)存儲對象頭,如果對象是非數組類型,用2字寬存儲對象頭。

      Tips:32位虛擬機中一個字寬等于4字節。

      34、Java對象頭長度

      Java對象頭長度

      35、Java對象頭的存儲結構

      32位JVM的Mark Word 默認存儲結構

      32位JVM的Mark Word 默認存儲結構

      36、Mark Word的狀態變化

      Mark Word 存儲的數據會隨著鎖標志為的變化而變化。

      Mark Word 存儲的數據會隨著鎖標志為的變化而變化。

      64位虛擬機下,Mark Word是64bit大小的

      64位虛擬機下,Mark Word是64bit大小的

      37、鎖的升降級規則

      Java SE 1.6 為了提高鎖的性能。引入了“偏向鎖”和輕量級鎖“。

      Java SE 1.6 中鎖有4種狀態。級別從低到高依次是:無鎖狀態、偏向鎖狀態、輕量級鎖狀態、重量級鎖狀態。

      鎖只能升級不能降級。

      38、偏向鎖

      大多數情況,鎖不僅不存在多線程競爭,而且總由同一線程多次獲得。當一個線程訪問同步塊并獲取鎖時,會在對象頭和棧幀中記錄存儲鎖偏向的線程ID,以后該線程在進入和退出同步塊時不需要進行 cas操作來加鎖和解鎖,只需測試一下對象頭 Mark Word里是否存儲著指向當前線程的偏向鎖。如果測試成功,表示線程已經獲得了鎖,如果失敗,則需要測試下Mark Word中偏向鎖的標示是否已經設置成1(表示當前時偏向鎖),如果沒有設置,則使用cas競爭鎖,如果設置了,則嘗試使用cas將對象頭的偏向鎖只想當前線程。

      39、關閉偏向鎖延遲

      java6和7中默認啟用,但是會在程序啟動幾秒后才激活,如果需要關閉延遲,

      -XX:BiasedLockingStartupDelay=0。

      40、如何關閉偏向鎖

      JVM參數關閉偏向鎖:-XX:-UseBiasedLocking=false,那么程序默認會進入輕量級鎖狀態。

      Tips:如果你可以確定程序的所有鎖通常情況處于競態,則可以選擇關閉。

      41、輕量級鎖

      線程在執行同步塊,jvm會現在當前線程的棧幀中創建用于儲存鎖記錄的空間。并將對象頭中的Mark Word復制到鎖記錄中。然后線程嘗試使用cas將對象頭中的Mark Word替換為之鄉鎖記錄的指針。如果成功,當前線程獲得鎖,如果失敗,表示其他線程競爭鎖,當前線程便嘗試使用自旋來獲取鎖。

      42、輕量鎖的解鎖

      輕量鎖解鎖時,會使原子操作cas將 displaced Mark Word 替換回對象頭,如果成功則表示沒有競爭發生,如果失敗,表示存在競爭,此時鎖就會膨脹為重量級鎖。

      43、鎖的優缺點對比

      鎖的優缺點對比

      44、什么是原子操作

      不可被中斷的一個或一系列操作

      45、Java如何實現原子操作

      Java中通過鎖和循環cas的方式來實現原子操作,JVM的CAS操作利用了處理器提供的CMPXCHG指令來實現的。自旋CAS實現的基本思路就是循環進行CAS操作直到成功為止。

      46、CAS實現原子操作的3大問題

      ABA問題,循環時間長消耗資源大,只能保證一個共享變量的原子操作

      47、什么是ABA問題

      問題:

      因為cas需要在操作值的時候,檢查值有沒有變化,如果沒有變化則更新,如果一個值原來是A,變成了B,又變成了A,那么使用cas進行檢測時會發現發的值沒有發生變化,其實是變過的。

      解決:

      添加版本號,每次更新的時候追加版本號,A-B-A —> 1A-2B-3A。

      從jdk1.5開始,Atomic包提供了一個類AtomicStampedReference來解決ABA的問題。

      48、CAS循環時間長占用資源大問題

      如果jvm能支持處理器提供的pause指令,那么效率會有一定的提升。

      一、它可以延遲流水線執行指令(de-pipeline),使cpu不會消耗過多的執行資源,延遲的時間取決于具體實現的版本,有些處理器延遲時間是0。

      二、它可以避免在退出循環的時候因內存順序沖突而引起的cpu流水線被清空,從而提高cpu執行效率。

      49、CAS只能保證一個共享變量原子操作

      一、對多個共享變量操作時,可以用鎖。

      二、可以把多個共享變量合并成一個共享變量來操作。比如,x=1,k=a,合并xk=1a,然后用cas操作xk。

      Tips:java 1.5開始,jdk提供了AtomicReference類來保證飲用對象之間的原子性,就可以把多個變量放在一個對象來進行cas操作。

      50、volatile關鍵字

      volatile 是輕量級的synchronized,它在多處理器開發中保證了共享變量的“可見性“。

      Java語言規范第3版對volatile定義如下,Java允許線程訪問共享變量,為了保證共享變量能準確和一致的更新,線程應該確保排它鎖單獨獲得這個變量。如果一個字段被聲明為volatile,Java線程內存模型所有線程看到這個變量的值是一致的。

      51、等待/通知機制

      一個線程修改了一個對象的值,而另一個線程感知到了變化,然后進行相應的操作。

      52、wait

      方法wait()的作用是使當前執行代碼的線程進行等待,wait()是Object類通用的方法,該方法用來將當前線程置入“預執行隊列”中,并在 wait()所在的代碼處停止執行,直到接到通知或中斷為止。

      在調用wait之前線程需要獲得該對象的對象級別的鎖。代碼體現上,即只能是同步方法或同步代碼塊內。調用wait()后當前線程釋放鎖。

      53、notify

      notify()也是Object類的通用方法,也要在同步方法或同步代碼塊內調用,該方法用來通知哪些可能燈光該對象的對象鎖的其他線程,如果有多個線程等待,則隨機挑選出其中一個呈wait狀態的線程,對其發出 通知 notify,并讓它等待獲取該對象的對象鎖。

      54、notify/notifyAll

      notify等于說將等待隊列中的一個線程移動到同步隊列中,而notifyAll是將等待隊列中的所有線程全部移動到同步隊列中。

      55、等待/通知經典范式

      等待

      通知

      56、ThreadLocal

      主要解決每一個線程想綁定自己的值,存放線程的私有數據。

      57、ThreadLocal使用

      獲取當前的線程的值通過get(),設置set(T) 方式來設置值。

      輸出:

      未設置過值Java小咖秀

      Tips:默認值為null

      58、解決get()返回null問題

      通過繼承重寫initialValue()方法即可。

      代碼實現:

      解決get()返回null問題

      輸出結果:

      Java小咖秀

      59、Lock接口

      鎖可以防止多個線程同時共享資源。Java5前程序是靠synchronized實現鎖功能。Java5之后,并發包新增Lock接口來實現鎖功能。

      60、Lock接口提供 synchronized不具備的主要特性

      Lock接口提供 synchronized不具備的主要特性

      61、重入鎖 ReentrantLock

      支持重進入的鎖,它表示該鎖能夠支持一個線程對資源的重復加鎖。除此之外,該鎖的還支持獲取鎖時的公平和非公平性選擇。

      62、重進入是什么意思?

      重進入是指任意線程在獲取到鎖之后能夠再次獲鎖而不被鎖阻塞。

      該特性主要解決以下兩個問題:

      1)鎖需要去識別獲取鎖的線程是否為當前占據鎖的線程,如果是則再次成功獲取。

      2)所得最終釋放。線程重復n次是獲取了鎖,隨后在第n次釋放該鎖后,其他線程能夠獲取到該鎖。

      63、ReentrantLock默認鎖?

      默認非公平鎖

      代碼為證:

      64、公平鎖和非公平鎖的區別

      公平性與否針對獲取鎖來說的,如果一個鎖是公平的,那么鎖的獲取順序就應該符合請求的絕對時間順序,也就是FIFO。

      65、讀寫鎖

      讀寫鎖允許同一時刻多個讀線程訪問,但是寫線程和其他寫線程均被阻塞。讀寫鎖維護一個讀鎖一個寫鎖,讀寫分離,并發性得到了提升。

      Java中提供讀寫鎖的實現類是ReentrantReadWriteLock。

      66、LockSupport工具

      定義了一組公共靜態方法,提供了最基本的線程阻塞和喚醒功能。

      67、Condition接口

      提供了類似Object監視器方法,與 Lock配合使用實現等待/通知模式。

      68、Condition使用

      代碼示例:

      69、ArrayBlockingQueue?

      一個由數據支持的有界阻塞隊列,此隊列FIFO原則對元素進行排序。隊列頭部在隊列中存在的時間最長,隊列尾部存在時間最短。

      70、PriorityBlockingQueue?

      一個支持優先級排序的無界阻塞隊列,但它不會阻塞數據生產者,而只會在沒有可消費的數據時,阻塞數據的消費者。

      71、DelayQueue?

      是一個支持延時獲取元素的使用優先級隊列的實現的無界阻塞隊列。隊列中的元素必須實現Delayed接口和 Comparable接口,在創建元素時可以指定多久才能從隊列中獲取當前元素。

      72、Java并發容器,你知道幾個?

      ConcurrentHashMap、CopyOnWriteArrayList 、CopyOnWriteArraySet 、ConcurrentLinkedQueue、

      ConcurrentLinkedDeque、ConcurrentSkipListMap、ConcurrentSkipListSet、ArrayBlockingQueue、

      LinkedBlockingQueue、LinkedBlockingDeque、PriorityBlockingQueue、SynchronousQueue、

      LinkedTransferQueue、DelayQueue

      73、ConcurrentHashMap

      并發安全版HashMap,java7中采用分段鎖技術來提高并發效率,默認分16段。Java8放棄了分段鎖,采用CAS,同時當哈希沖突時,當鏈表的長度到8時,會轉化成紅黑樹。(如需了解細節,見jdk中代碼)

      74、ConcurrentLinkedQueue

      基于鏈接節點的無界線程安全隊列,它采用先進先出的規則對節點進行排序,當我們添加一個元素的時候,它會添加到隊列的尾部,當我們獲取一個元素時,它會返回隊列頭部的元素。它采用cas算法來實現。(如需了解細節,見jdk中代碼)

      75、什么是阻塞隊列?

      阻塞隊列是一個支持兩個附加操作的隊列,這兩個附加操作支持阻塞的插入和移除方法。

      1)支持阻塞的插入方法:當隊列滿時,隊列會阻塞插入元素的線程,直到隊列不滿。

      2)支持阻塞的移除方法:當隊列空時,獲取元素的線程會等待隊列變為非空。

      76、阻塞隊列常用的應用場景?

      常用于生產者和消費者場景,生產者是往隊列里添加元素的線程,消費者是從隊列里取元素的線程。阻塞隊列正好是生產者存放、消費者來獲取的容器。

      77、Java里的阻塞的隊列


      78、Fork/Join

      java7提供的一個用于并行執行任務的框架,把一個大任務分割成若干個小任務,最終匯總每個小任務結果的后得到大任務結果的框架。

      79、工作竊取算法

      是指某個線程從其他隊列里竊取任務來執行。當大任務被分割成小任務時,有的線程可能提前完成任務,此時閑著不如去幫其他沒完成工作線程。此時可以去其他隊列竊取任務,為了減少競爭,通常使用雙端隊列,被竊取的線程從頭部拿,竊取的線程從尾部拿任務執行。

      80、工作竊取算法的有缺點

      優點:充分利用線程進行并行計算,減少了線程間的競爭。

      缺點:有些情況下還是存在競爭,比如雙端隊列中只有一個任務。這樣就消耗了更多資源。

      81、Java中原子操作更新基本類型,Atomic包提供了哪幾個類?

      AtomicBoolean:原子更新布爾類型

      AtomicInteger:原子更新整形

      AtomicLong:原子更新長整形

      82、Java中原子操作更新數組,Atomic包提供了哪幾個類?

      AtomicIntegerArray: 原子更新整形數據里的元素

      AtomicLongArray: 原子更新長整形數組里的元素

      AtomicReferenceArray: 原子更新飲用類型數組里的元素

      AtomicIntegerArray: 主要提供原子方式更新數組里的整形

      83、Java中原子操作更新引用類型,Atomic包提供了哪幾個類?

      如果原子需要更新多個變量,就需要用引用類型了。

      AtomicReference : 原子更新引用類型

      AtomicReferenceFieldUpdater: 原子更新引用類型里的字段。

      AtomicMarkableReference: 原子更新帶有標記位的引用類型。標記位用boolean類型表示,構造方法時AtomicMarkableReference(V initialRef,boolean initialMark)

      84、Java中原子操作更新字段類,Atomic包提供了哪幾個類?

      AtomiceIntegerFieldUpdater: 原子更新整形字段的更新器

      AtomiceLongFieldUpdater: 原子更新長整形字段的更新器

      AtomiceStampedFieldUpdater: 原子更新帶有版本號的引用類型,將整數值

      85、JDK并發包中提供了哪幾個比較常見的處理并發的工具類?

      提供并發控制手段: CountDownLatch、CyclicBarrier、Semaphore

      線程間數據交換: Exchanger

      86、CountDownLatch

      允許一個或多個線程等待其他線程完成操作。

      CountDownLatch的構造函數接受一個int類型的參數作為計數器,你想等待n個點完成,就傳入n。

      兩個重要的方法:

      countDown() : 調用時,n會減1。

      await() : 調用會阻塞當前線程,直到n變成0。

      await(long time,TimeUnit unit) : 等待特定時間后,就不會繼續阻塞當前線程。

      tips:計數器必須大于等于0,當為0時,await就不會阻塞當前線程。

      不提供重新初始化或修改內部計數器的值的功能。

      87、CyclicBarrier

      可循環使用的屏障。

      讓一組線程到達一個屏障(也可以叫同步點)時被阻塞,直到最后一個線程到達屏障時,屏障才會開門,所有被屏障攔截的線程才會繼續運行。

      CyclicBarrier默認構造放時CyclicBarrier(int parities) ,其參數表示屏障攔截的線程數量,每個線程調用await方法告訴CyclicBarrier我已經到達屏障,然后當前線程被阻塞。

      88、CountDownLatch與CyclicBarrier區別

      CountDownLatch:

      計數器:計數器只能使用一次。

      等待:一個線程或多個等待另外n個線程完成之后才能執行。

      CyclicBarrier:

      計數器:計數器可以重置(通過reset()方法)。

      等待:n個線程相互等待,任何一個線程完成之前,所有的線程都必須等待。

      89、Semaphore

      用來控制同時訪問資源的線程數量,通過協調各個線程,來保證合理的公共資源的訪問。

      應用場景:流量控制,特別是公共資源有限的應用場景,比如數據鏈接,限流等。

      90、Exchanger

      Exchanger是一個用于線程間協作的工具類,它提供一個同步點,在這個同步點上,兩個線程可以交換彼此的數據。比如第一個線程執行exchange()方法,它會一直等待第二個線程也執行exchange,當兩個線程都到同步點,就可以交換數據了。

      一般來說為了避免一直等待的情況,可以使用exchange(V x,long timeout,TimeUnit unit),設置最大等待時間。

      Exchanger可以用于遺傳算法。

      91、為什么使用線程池

      幾乎所有需要異步或者并發執行任務的程序都可以使用線程池。合理使用會給我們帶來以下好處。

      降低系統消耗:重復利用已經創建的線程降低線程創建和銷毀造成的資源消耗。

      提高響應速度:當任務到達時,任務不需要等到線程創建就可以立即執行。

      提供線程可以管理性:可以通過設置合理分配、調優、監控。91、線程池工作流程

      1)判斷核心線程池里的線程是否都有在執行任務,否->創建一個新工作線程來執行任務。是->走下個流程。

      2)判斷工作隊列是否已滿,否->新任務存儲在這個工作隊列里,是->走下個流程。

      3)判斷線程池里的線程是否都在工作狀態,否->創建一個新的工作線程來執行任務,

      是->走下個流程。

      4)按照設置的策略來處理無法執行的任務。

      92、創建線程池參數有哪些,作用?

      創建線程池參數有哪些,作用

      1)corePoolSize:核心線程池大小,當提交一個任務時,線程池會創建一個線程來執行任務,即使其他空閑的核心線程能夠執行新任務也會創建,等待需要執行的任務數大于線程核心大小就不會繼續創建。

      2)maximumPoolSize:線程池最大數,允許創建的最大線程數,如果隊列滿了,并且已經創建的線程數小于最大線程數,則會創建新的線程執行任務。如果是無界隊列,這個參數基本沒用。

      3)keepAliveTime:線程保持活動時間,線程池工作線程空閑后,保持存活的時間,所以如果任務很多,并且每個任務執行時間較短,可以調大時間,提高線程利用率。

      4)unit: 線程保持活動時間單位,天(DAYS)、小時(HOURS)、分鐘(MINUTES、毫秒MILLISECONDS)、微秒(MICROSECONDS)、納秒(NANOSECONDS)

      5)workQueue: 任務隊列,保存等待執行的任務的阻塞隊列。

      一般來說可以選擇如下阻塞隊列:

      ArrayBlockingQueue:基于數組的有界阻塞隊列。

      LinkedBlockingQueue:基于鏈表的阻塞隊列。

      SynchronizedQueue:一個不存儲元素的阻塞隊列。

      PriorityBlockingQueue:一個具有優先級的阻塞隊列。

      6)threadFactory:設置創建線程的工廠,可以通過線程工廠給每個創建出來的線程設置更有意義的名字。

      handler: 飽和策略也叫拒絕策略。當隊列和線程池都滿了,即達到飽和狀態。所以需要采取策略來處理新的任務。默認策略是AbortPolicy。

      AbortPolicy:直接拋出異常。

      CallerRunsPolicy: 調用者所在的線程來運行任務。

      DiscardOldestPolicy:丟棄隊列里最近的一個任務,并執行當前任務。

      DiscardPolicy:不處理,直接丟掉。

      當然可以根據自己的應用場景,實現RejectedExecutionHandler接口自定義策略。

      93、向線程池提交任務

      可以使用execute()和submit() 兩種方式提交任務。

      execute():無返回值,所以無法判斷任務是否被執行成功。

      submit():用于提交需要有返回值的任務。線程池返回一個future類型的對象,通過這個future對象可以判斷任務是否執行成功,并且可以通過future的get()來獲取返回值,get()方法會阻塞當前線程知道任務完成。get(long timeout,TimeUnit unit)可以設置超市時間。

      94、關閉線程池

      可以通過shutdown()或shutdownNow()來關閉線程池。它們的原理是遍歷線程池中的工作線程,然后逐個調用線程的interrupt來中斷線程,所以無法響應終端的任務可以能永遠無法停止。

      shutdownNow首先將線程池狀態設置成STOP,然后嘗試停止所有的正在執行或者暫停的線程,并返回等待執行任務的列表。

      shutdown只是將線程池的狀態設置成shutdown狀態,然后中斷所有沒有正在執行任務的線程。

      只要調用兩者之一,isShutdown就會返回true,當所有任務都已關閉,isTerminaed就會返回true。

      一般來說調用shutdown方法來關閉線程池,如果任務不一定要執行完,可以直接調用shutdownNow方法。

      95、線程池如何合理設置

      配置線程池可以從以下幾個方面考慮。

      任務是cpu密集型、IO密集型或者混合型

      任務優先級,高中低。

      任務時間執行長短。

      任務依賴性:是否依賴其他系統資源。

      cpu密集型可以配置可能小的線程,比如 n + 1個線程。

      io密集型可以配置較多的線程,如 2n個線程。

      混合型可以拆成io密集型任務和cpu密集型任務,

      如果兩個任務執行時間相差大,否->分解后執行吞吐量將高于串行執行吞吐量。

      否->沒必要分解。

      可以通過Runtime.getRuntime().availableProcessors()來獲取cpu個數。

      建議使用有界隊列,增加系統的預警能力和穩定性。

      96、Executor

      從JDK5開始,把工作單元和執行機制分開。工作單元包括Runnable和Callable,而執行機制由Executor框架提供。

      97、Executor框架的主要成員

      ThreadPoolExecutor :可以通過工廠類Executors來創建。

      可以創建3種類型的ThreadPoolExecutor:SingleThreadExecutor、FixedThreadPool、CachedThreadPool。

      ScheduledThreadPoolExecutor :可以通過工廠類Executors來創建。

      可以創建2中類型的ScheduledThreadPoolExecutor:ScheduledThreadPoolExecutor、SingleThreadScheduledExecutor

      Future接口:Future和實現Future接口的FutureTask類來表示異步計算的結果。

      Runnable和Callable:它們的接口實現類都可以被ThreadPoolExecutor或ScheduledThreadPoolExecutor執行。Runnable不能返回結果,Callable可以返回結果。

      98、FixedThreadPool

      可重用固定線程數的線程池。

      查看源碼:

      可重用固定線程數的線程池

      corePoolSize 和maxPoolSize都被設置成我們設置的nThreads。

      當線程池中的線程數大于corePoolSize ,keepAliveTime為多余的空閑線程等待新任務的最長時間,超過這個時間后多余的線程將被終止,如果設為0,表示多余的空閑線程會立即終止。

      工作流程:

      1)當前線程少于corePoolSize,創建新線程執行任務。

      2)當前運行線程等于corePoolSize,將任務加入LinkedBlockingQueue。

      3)線程執行完1中的任務,會循環反復從LinkedBlockingQueue獲取任務來執行。

      LinkedBlockingQueue作為線程池工作隊列(默認容量Integer.MAX_VALUE)。因此可能會造成如下贏下。

      1)當線程數等于corePoolSize時,新任務將在隊列中等待,因為線程池中的線程不會超過corePoolSize。

      2)maxnumPoolSize等于說是一個無效參數。

      3)keepAliveTime等于說也是一個無效參數。

      4)運行中的FixedThreadPool(未執行shundown或shundownNow))則不會調用拒絕策略。

      5)由于任務可以不停的加到隊列,當任務越來越多時很容易造成OOM。

      99、CachedThreadPool

      根據需要創建新線程的線程池。

      查看源碼:

      corePoolSize設置為0,maxmumPoolSize為Integer.MAX_VALUE。keepAliveTime為60秒。

      工作流程:

      1)首先執行SynchronousQueue.offer (Runnable task)。如果當前maximumPool 中有空閑線程正在執行S ynchronousQueue.poll(keepAliveTIme,TimeUnit.NANOSECONDS),那么主線程執行offer操作與空閑線程執行的poll操作配對成功,主線程把任務交給空閑線程執行,execute方 法執行完成;否則執行下面的步驟2。

      當初始maximumPool為空或者maximumPool中當前沒有空閑線程時,將沒有線程執行 SynchronousQueue.poll (keepAliveTime,TimeUnit.NANOSECONDS)。這種情況下,步驟 1將失 敗。此時CachedThreadPool會創建一個新線程執行任務,execute()方法執行完成。3)在步驟2中新創建的線程將任務執行完后,會執行SynchronousQueue.poll (keepAliveTime,TimeUnit.NANOSECONDS)。這個poll操作會讓空閑線程最多在SynchronousQueue中等待60秒鐘。如果60秒鐘內主線程提交了一個新任務(主線程執行步驟1),那么這個空閑線程將執行主線程提交的新任務;否則,這個空閑線程將終止。由于空閑60秒的空閑線程會被終止,因此長時間保持空閑的CachedThreadPool不會使用任何資源。

      免責聲明:內容來源于公開網絡,若涉及侵權聯系盡快刪除!

      預約申請免費試聽課

      填寫下面表單即可預約申請免費試聽!怕錢不夠?可就業掙錢后再付學費! 怕學不會?助教全程陪讀,隨時解惑!擔心就業?一地學習,可全國推薦就業!

      上一篇:Java程序員面試如何獲得高薪
      下一篇:Java面試技巧及注意事項匯總(解析)
      Java企業面試題及答案資料大全

      Java企業面試題及答案資料大全

      Java大廠面試題(詳細總結)

      Java大廠面試題(詳細總結)

      Java面試HR必問面試題目匯總

      Java面試HR必問面試題目匯總

      Java基礎面試題目匯總(帶答案)

      Java基礎面試題目匯總(帶答案)

      • 掃碼領取資料

        回復關鍵字:視頻資料

        免費領取 達內課程視頻學習資料

      • 視頻學習QQ群

        添加QQ群:1143617948

        免費領取達內課程視頻學習資料

      Copyright ? 2021 Tedu.cn All Rights Reserved 京ICP備08000853號-56 京公網安備 11010802029508號 達內時代科技集團有限公司 版權所有

      選擇城市和中心
      貴州省

      福建省

      • 達內廈門軟件園中心
      廣西省

      海南省

      久草在線歐美激情,久草在線國產自拍,久草在線日韓無碼,久草在線 百度 好搜 搜狗
      <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <蜘蛛词>| <文本链> <文本链> <文本链> <文本链> <文本链> <文本链>