Java核心篇之多线程---day1
Java面試之多線程—day1
一. 線程中sleep方法與wait方法有什么區(qū)別?
對于 sleep()方法,我們首先要知道該方法是屬于 Thread 類中的。而 wait()方法,則是屬于Object 類中的。
在調(diào)用 sleep()方法的過程中, 線程不會釋放對象鎖。而當調(diào)用 wait()方法的時候,線程會放棄對象鎖,進入與該對象相關(guān)的等待池中,只有針對此對象當?shù)却龝r間到了的時候,或者調(diào)用 notify()方法后才會返回對象鎖。
二. Java中線程的實現(xiàn)方式?同步的方式?
(繼承thread類,實現(xiàn)runnable接口,通過callable和future來實現(xiàn)(call方法有返回值和聲明異常),使用線程池例如executor框架來實現(xiàn))
三. 同步鎖與死鎖
同步鎖:當多個線程同時訪問同一個數(shù)據(jù)時,很容易出現(xiàn)問題。為了避免這種情況出現(xiàn),我們要保證線程
同步互斥,就是指并發(fā)執(zhí)行的多個線程,在同一時間內(nèi)只允許一個線程訪問共享數(shù)據(jù)。 Java 中可
以使用 synchronized 關(guān)鍵字來取得一個對象的同步鎖。
死鎖:何為死鎖,就是多個線程同時被阻塞,它們中的一個或者全部都在等待某個資源被釋放。
線程池的原理:
線程池做的工作主要是控制運行的線程的數(shù)量,處理過程中將任務放入隊列,然后在線程創(chuàng)建后
啟動這些任務,如果線程數(shù)量超過了最大數(shù)量超出數(shù)量的線程排隊等候,等其它線程執(zhí)行完畢,
再從隊列中取出任務來執(zhí)行。 他的主要特點為: 線程復用; 控制最大并發(fā)數(shù); 管理線程。
線程池的組成:
一個線程池主要有四個方面組成:
1. 線程池管理器:用于創(chuàng)建并管理線程池
2. 工作線程:線程池中的線程
3. 任務接口:每個任務必須實現(xiàn)的接口,用于工作線程調(diào)度其運行
4. 任務隊列:用于存放待處理的任務,提供一種緩沖機制
少時間內(nèi)會被銷毀。**
4. unit: keepAliveTime 的單位。
5. workQueue:任務隊列,被提交但尚未被執(zhí)行的任務。
6. threadFactory:線程工廠,用于創(chuàng)建線程,一般用默認的即可。
7. handler:拒絕策略,當任務太多來不及處理,如何拒絕任務。
線程池中的線程已經(jīng)用完了,無法繼續(xù)為新任務服務,同時,等待隊列也已經(jīng)排滿了,再也
塞不下新任務了。這時候我們就需要拒絕策略機制合理的處理這個問題。
JDK 內(nèi)置的拒絕策略如下:
1. AbortPolicy : 直接拋出異常,阻止系統(tǒng)正常運行。
2. CallerRunsPolicy : 只要線程池未關(guān)閉,該策略直接在調(diào)用者線程中,運行當前被丟棄的
任務。顯然這樣做不會真的丟棄任務,但是,任務提交線程的性能極有可能會急劇下降。
3. DiscardOldestPolicy : 丟棄最老的一個請求,也就是即將被執(zhí)行的一個任務,并嘗試再
次提交當前任務。
4. DiscardPolicy : 該策略默默地丟棄無法處理的任務,不予任何處理。如果允許任務丟
失,這是最好的一種方案。
以上內(nèi)置拒絕策略均實現(xiàn)了 RejectedExecutionHandler 接口,若以上策略仍無法滿足實際
需要,完全可以自己擴展 RejectedExecutionHandler 接口。
6. Java線程池的工作原理:
1. 線程池剛創(chuàng)建時,里面沒有一個線程。任務隊列是作為參數(shù)傳進來的。不過,就算隊列里面
有任務,線程池也不會馬上執(zhí)行它們。
2. 當調(diào)用 execute() 方法添加一個任務時,線程池會做如下判斷:
a) 如果正在運行的線程數(shù)量小于 corePoolSize,那么馬上創(chuàng)建線程運行這個任務;
b) 如果正在運行的線程數(shù)量大于或等于 corePoolSize,那么將這個任務放入隊列;
c) 如果這時候隊列滿了,而且正在運行的線程數(shù)量小于 maximumPoolSize,那么還是要
創(chuàng)建非核心線程立刻運行這個任務;
d) 如果隊列滿了,而且正在運行的線程數(shù)量大于或等于 maximumPoolSize,那么線程池
會拋出異常 RejectExecutionException。
3. 當一個線程完成任務時,它會從隊列中取下一個任務來執(zhí)行。
4. 當一個線程無事可做,超過一定的時間( keepAliveTime)時,線程池會判斷,如果當前運
行的線程數(shù)大于 corePoolSize,那么這個線程就被停掉。所以線程池的所有任務完成后,它
最終會收縮到 corePoolSize 的大小。
線程與進程的區(qū)別:
線程的生命周期(狀態(tài))
1. 新建(new):當程序使用 new 關(guān)鍵字創(chuàng)建了一個線程之后,該線程就處于新建狀態(tài),此時僅由 JVM 為其分配
內(nèi)存,并初始化其成員變量的值.
2. 就緒(runnable):當線程對象調(diào)用了 start()方法之后,該線程處于就緒狀態(tài)。 Java 虛擬機會為其創(chuàng)建方法調(diào)用棧和
程序計數(shù)器,等待調(diào)度運行。
3. 運行(running):如果處于就緒狀態(tài)的線程獲得了 CPU,開始執(zhí)行 run()方法的線程執(zhí)行體,則該線程處于運行狀
態(tài)
4. 阻塞(blocked):阻塞狀態(tài)是指線程因為某種原因放棄了 cpu 使用權(quán),也即讓出了 cpu timeslice,暫時停止運行。
直到線程進入阻塞(runnable)狀態(tài),才有機會再次獲得 cpu timeslice 轉(zhuǎn)到運行(running)狀
態(tài)。阻塞的情況分三種:
5. 死亡(dead):線程會以下面三種方式結(jié)束,結(jié)束后就是死亡狀態(tài)。
start方法和run方法的區(qū)別:
1)。 調(diào)用start方法來啟動多線程,這時候蔡真正的實現(xiàn)多線程運行,這時無需等待run方法執(zhí)行完畢就可以直接繼續(xù)執(zhí)行下面的代碼,這個時候線程是處于就緒(runnable) 狀態(tài)。
2)。run方法稱為線程體,調(diào)用run方法的時候,線程進入運行態(tài),當run方法執(zhí)行完畢時,線程就結(jié)束了。
守護線程
守護線程也叫“服務線程”,為用戶提供公共服務,在沒有用戶可提供的時候會自動離開。守護線程的優(yōu)先級比較低。
垃圾回收線程就是一個經(jīng)典的守護線程,當我們程序中不在有其他任何運行的線程時,程序就不會產(chǎn)生垃圾,垃圾回收器也就無事可做,垃圾回收器就會自動離開。
總結(jié)
以上是生活随笔為你收集整理的Java核心篇之多线程---day1的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: UP装机部署步骤大纲
- 下一篇: Java面试宝典————基础篇