java線程圖
A. java如何實現多線程繪圖
首先,如果你只是要實現電子時鍾,根本就不需要用到多線程。
如果你真的是要使用,就新建一個類,實現Runnable介面就是了。
如:
class MyThread1 implements Runnable{
public MyThread(){
}
public void run(){
}
}
使用的時候,就:
Thread myThread=new Thread(new MyThread());
myThread.start();
如果要畫圖,你就直接把組件通過構造方法傳到MyThread中就是了
B. 再見了Future,圖解JDK21虛擬線程的結構化並發
Java為我們提供了多種並發編程手段,本文將探討一些關鍵概念和方法。首先,簡要介紹基礎方法,即使用Lambda表達式創建平台線程。然而,這種方法在大多數應用程序伺服器中不被鼓勵,因此轉向更高級的解決方案,如Java的Futures。
JDK 5引入了Futures類,允許開發者將任務提交到線程池並返回結果。通過ExecutorService介面實現任務提交,它是一個用於管理任務執行的機制。然而,Futures存在一些問題,例如,使用Platform線程時,獲取結果的操作會阻塞線程,這可能導致性能問題。
Java 21的虛擬線程(Virtual Threads)提供了改進,通過使用Virtual Threads,當使用future.get()方法阻塞線程時,底層的平台線程不會被阻塞。這解決了Futures中的一個關鍵問題。同時,使用CompletableFuture Pipelines也可以解決阻塞問題,但本文將重點介紹Virtual Threads的優勢。
結構化並發的概念旨在更好地組織和管理任務執行。它強調了一個塊(如方法或塊)內啟動的所有任務應在該塊結束時終止。這樣可以實現更清晰的代碼結構和易於理解的執行順序。Java 21中引入的StructuredTaskScope類試圖提供更干凈的結構化並發模型,它能夠更好地處理任務之間的關系。
StructuredTaskScope類能夠自動取消在任一任務失敗時執行的後續任務,確保沒有未完成的任務遺留。通過使用StructuredTaskScope創建的結構化任務范圍,可以實現代碼的模塊化和一致性,提高開發效率。
本文示例展示了一個用例,其中兩個任務可以並行運行,然後將結果合並到單個對象中返回。通過使用StructuredTaskScope.ShutdownOnFailure()方法,可以確保在任一任務失敗時,其他任務自動被取消。這避免了等待時間過長或保留未明確終止的線程的問題。
在編寫使用StructuredTaskScope的代碼時,開發者需要確保任務能夠正確處理取消期間設置的中斷標志。任務應該檢查並適當終止,以確保用例的響應性。總的來說,StructuredTaskScope和Virtual Threads共同提供了一種強大的並發編程方法,適用於將任務拆分為多個子任務的復雜用例。
C. 簡速java語言中線程對象都有哪些狀態,這些狀態如何變化
線程的狀態轉換是線程式控制制的基礎。線程狀態總的可分為五大狀態:分別是生、死、可運行、運行、等待/阻塞。用一個圖來描述如下:
1、新狀態:線程對象已經創建,還沒有在其上調用start()方法。
2、可運行狀態:當線程有資格運行,但調度程序還沒有把它選定為運行線程時線程所處的狀態。當start()方法調用時,線程首先進入可運行狀態。在線程運行之後或者從阻塞、等待或睡眠狀態回來後,也返回到可運行狀態。
3、運行狀態:線程調度程序從可運行池中選擇一個線程作為當前線程時線程所處的狀態。這也是線程進入運行狀態的唯一一種方式。
4、等待/阻塞/睡眠狀態:這是線程有資格運行時它所處的狀態。實際上這個三狀態組合為一種,其共同點是:線程仍舊是活的,但是當前沒有條件運行。換句話說,它是可運行的,但是如果某件事件出現,他可能返回到可運行狀態。
5、死亡態:當線程的run()方法完成時就認為它死去。這個線程對象也許是活的,但是,它已經不是一個單獨執行的線程。線程一旦死亡,就不能復生。 如果在一個死去的線程上調用start()方法,會拋出java.lang.IllegalThreadStateException異常。
有關詳細狀態轉換圖可以參看本人的「Java多線程編程總結」中的圖
二、阻止線程執行
對於線程的阻止,考慮一下三個方面,不考慮IO阻塞的情況:
睡眠;
等待;
因為需要一個對象的鎖定而被阻塞。
1、睡眠
Thread.sleep(long millis)和Thread.sleep(long millis, int nanos)靜態方法強制當前正在執行的線程休眠(暫停執行),以「減慢線程」。當線程睡眠時,它入睡在某個地方,在蘇醒之前不會返回到可運行狀態。當睡眠時間到期,則返回到可運行狀態。
線程睡眠的原因:線程執行太快,或者需要強制進入下一輪,因為Java規范不保證合理的輪換。
睡眠的實現:調用靜態方法。
try {
Thread.sleep(123);
} catch (InterruptedException e) {
e.printStackTrace();
}
睡眠的位置:為了讓其他線程有機會執行,可以將Thread.sleep()的調用放線程run()之內。這樣才能保證該線程執行過程中會睡眠。
例如,在前面的例子中,將一個耗時的操作改為睡眠,以減慢線程的執行。可以這么寫:
public void run() {
for(int i = 0;i<5;i++){
// 很耗時的操作,用來減慢線程的執行
// for(long k= 0; k <100000000;k++);
try {
Thread.sleep(3);
} catch (InterruptedException e) {
e.printStackTrace(); .
}
System.out.println(this.getName()+" :"+i);
}
}
D. java 線程池 工作隊列是如何工作的
使用線程池的好處
1、降低資源消耗
可以重復利用已創建的線程降低線程創建和銷毀造成的消耗。
2、提高響應速度
當任務到達時,任務可以不需要等到線程創建就能立即執行。
3、提高線程的可管理性
線程是稀缺資源,如果無限制地創建,不僅會消耗系統資源,還會降低系統的穩定性,使用線程池可以進行統一分配、調優和監控
線程池的工作原理
首先我們看下當一個新的任務提交到線程池之後,線程池是如何處理的
1、線程池判斷核心線程池裡的線程是否都在執行任務。如果不是,則創建一個新的工作線程來執行任務。如果核心線程池裡的線程都在執行任務,則執行第二步。
2、線程池判斷工作隊列是否已經滿。如果工作隊列沒有滿,則將新提交的任務存儲在這個工作隊列里進行等待。如果工作隊列滿了,則執行第三步
3、線程池判斷線程池的線程是否都處於工作狀態。如果沒有,則創建一個新的工作線程來執行任務。如果已經滿了,則交給飽和策略來處理這個任務
線程池飽和策略
這里提到了線程池的飽和策略,那我們就簡單介紹下有哪些飽和策略:
AbortPolicy
為Java線程池默認的阻塞策略,不執行此任務,而且直接拋出一個運行時異常,切記ThreadPoolExecutor.execute需要try catch,否則程序會直接退出。
DiscardPolicy
直接拋棄,任務不執行,空方法
DiscardOldestPolicy
從隊列裡面拋棄head的一個任務,並再次execute 此task。
CallerRunsPolicy
在調用execute的線程裡面執行此command,會阻塞入口
用戶自定義拒絕策略(最常用)
實現RejectedExecutionHandler,並自己定義策略模式
下我們以ThreadPoolExecutor為例展示下線程池的工作流程圖
3.jpg
關鍵方法源碼分析
我們看看核心方法添加到線程池方法execute的源碼如下:
// //Executes the given task sometime in the future. The task //may execute in a new thread or in an existing pooled thread. // // If the task cannot be submitted for execution, either because this // executor has been shutdown or because its capacity has been reached, // the task is handled by the current {@code RejectedExecutionHandler}. // // @param command the task to execute // @throws RejectedExecutionException at discretion of // {@code RejectedExecutionHandler}, if the task // cannot be accepted for execution // @throws NullPointerException if {@code command} is null // public void execute(Runnable command) { if (command == null) throw new NullPointerException(); // // Proceed in 3 steps: // // 1. If fewer than corePoolSize threads are running, try to // start a new thread with the given command as its first // task. The call to addWorker atomically checks runState and // workerCount, and so prevents false alarms that would add // threads when it shouldn't, by returning false. // 翻譯如下: // 判斷當前的線程數是否小於corePoolSize如果是,使用入參任務通過addWord方法創建一個新的線程, // 如果能完成新線程創建exexute方法結束,成功提交任務 // 2. If a task can be successfully queued, then we still need // to double-check whether we should have added a thread // (because existing ones died since last checking) or that // the pool shut down since entry into this method. So we // recheck state and if necessary roll back the enqueuing if // stopped, or start a new thread if there are none. // 翻譯如下: // 在第一步沒有完成任務提交;狀態為運行並且能否成功加入任務到工作隊列後,再進行一次check,如果狀態 // 在任務加入隊列後變為了非運行(有可能是在執行到這里線程池shutdown了),非運行狀態下當然是需要 // reject;然後再判斷當前線程數是否為0(有可能這個時候線程數變為了0),如是,新增一個線程; // 3. If we cannot queue task, then we try to add a new // thread. If it fails, we know we are shut down or saturated // and so reject the task. // 翻譯如下: // 如果不能加入任務到工作隊列,將嘗試使用任務新增一個線程,如果失敗,則是線程池已經shutdown或者線程池 // 已經達到飽和狀態,所以reject這個他任務 // int c = ctl.get(); // 工作線程數小於核心線程數 if (workerCountOf(c) < corePoolSize) { // 直接啟動新線程,true表示會再次檢查workerCount是否小於corePoolSize if (addWorker(command, true)) return; c = ctl.get(); } // 如果工作線程數大於等於核心線程數 // 線程的的狀態未RUNNING並且隊列notfull if (isRunning(c) && workQueue.offer(command)) { // 再次檢查線程的運行狀態,如果不是RUNNING直接從隊列中移除 int recheck = ctl.get(); if (! isRunning(recheck) && remove(command)) // 移除成功,拒絕該非運行的任務 reject(command); else if (workerCountOf(recheck) == 0) // 防止了SHUTDOWN狀態下沒有活動線程了,但是隊列里還有任務沒執行這種特殊情況。 // 添加一個null任務是因為SHUTDOWN狀態下,線程池不再接受新任務 addWorker(null, false); } // 如果隊列滿了或者是非運行的任務都拒絕執行 else if (!addWorker(command, false)) reject(command); }
E. 鑳借В閲婁竴涓媕ava鐨勭嚎紼嬬殑浣跨敤
闅忕潃璁$畻鏈虹殑椋為熷彂灞曪紝涓浜鴻$畻鏈轟笂鐨勬搷浣滅郴緇熶篃綰風悍閲囩敤澶氫換鍔″拰鍒嗘椂璁捐★紝灝嗘棭鏈熷彧鏈夊ぇ鍨嬭$畻鏈烘墠鍏鋒湁鐨勭郴緇熺壒鎬у甫鍒頒簡涓浜鴻$畻鏈虹郴緇熶腑銆備竴鑸鍙浠ュ湪鍚屼竴鏃墮棿鍐呮墽琛屽氫釜紼嬪簭鐨勬搷浣滅郴緇熼兘鏈夎繘紼嬬殑姒傚康銆備竴涓榪涚▼灝辨槸涓涓鎵ц屼腑鐨勭▼搴忥紝鑰屾瘡涓涓榪涚▼閮芥湁鑷宸辯嫭絝嬬殑涓鍧楀唴瀛樼┖闂淬佷竴緇勭郴緇熻祫婧愩傚湪榪涚▼姒傚康涓錛屾瘡涓涓榪涚▼鐨勫唴閮ㄦ暟鎹鍜岀姸鎬侀兘鏄瀹屽叏鐙絝嬬殑銆侸ava紼嬪簭閫氳繃嫻佹帶鍒舵潵鎵ц岀▼搴忔祦錛岀▼搴忎腑鍗曚釜欏哄簭鐨勬祦鎺у埗縐頒負綰跨▼錛屽氱嚎紼嬪垯鎸囩殑鏄鍦ㄥ崟涓紼嬪簭涓鍙浠ュ悓鏃惰繍琛屽氫釜涓嶅悓鐨勭嚎紼嬶紝鎵ц屼笉鍚岀殑浠誨姟銆傚氱嚎紼嬫剰鍛崇潃涓涓紼嬪簭鐨勫氳岃鍙ュ彲浠ョ湅涓婂幓鍑犱箮鍦ㄥ悓涓鏃墮棿鍐呭悓鏃惰繍琛屻
綰跨▼涓庤繘紼嬬浉浼礆紝鏄涓孌靛畬鎴愭煇涓鐗瑰畾鍔熻兘鐨勪唬鐮侊紝鏄紼嬪簭涓鍗曚釜欏哄簭鐨勬祦鎺у埗錛涗絾涓庤繘紼嬩笉鍚岀殑鏄錛屽悓綾葷殑澶氫釜綰跨▼鏄鍏變韓涓鍧楀唴瀛樼┖闂村拰涓緇勭郴緇熻祫婧愶紝鑰岀嚎紼嬫湰韜鐨勬暟鎹閫氬父鍙鏈夊井澶勭悊鍣ㄧ殑瀵勫瓨鍣ㄦ暟鎹錛屼互鍙婁竴涓渚涚▼搴忔墽琛屾椂浣跨敤鐨勫爢鏍堛傛墍浠ョ郴緇熷湪浜х敓涓涓綰跨▼錛屾垨鑰呭湪鍚勪釜綰跨▼涔嬮棿鍒囨崲鏃訛紝璐熸媴瑕佹瘮榪涚▼灝忕殑澶氾紝姝e洜濡傛わ紝綰跨▼琚縐頒負杞昏礋鑽瘋繘紼嬶紙light-weight process錛夈備竴涓榪涚▼涓鍙浠ュ寘鍚澶氫釜綰跨▼銆
涓涓綰跨▼鏄涓涓紼嬪簭鍐呴儴鐨勯『搴忔帶鍒舵祦銆
1. 榪涚▼錛氭瘡涓榪涚▼閮芥湁鐙絝嬬殑浠g爜鍜屾暟鎹絀洪棿錛堣繘紼嬩笂涓嬫枃錛 錛岃繘紼嬪垏鎹㈢殑寮閿澶с
2. 綰跨▼錛氳交閲忕殑榪涚▼錛屽悓涓綾葷嚎紼嬪叡浜浠g爜鍜屾暟鎹絀洪棿錛屾瘡涓綰跨▼鏈夌嫭絝嬬殑榪愯屾爤鍜岀▼搴忚℃暟鍣錛圥C錛夛紝綰跨▼鍒囨崲鐨勫紑閿灝忋
3. 澶氳繘紼嬶細鍦ㄦ搷浣滅郴緇熶腑錛岃兘鍚屾椂榪愯屽氫釜浠誨姟紼嬪簭銆
4. 澶氱嚎紼嬶細鍦ㄥ悓涓搴旂敤紼嬪簭涓錛屾湁澶氫釜欏哄簭嫻佸悓鏃舵墽琛屻
6錛1錛1 綰跨▼鐨勬傚康妯″瀷
Java鍐呭湪鏀鎸佸氱嚎紼嬶紝瀹冪殑鎵鏈夌被閮芥槸鍦ㄥ氱嚎紼嬩笅瀹氫箟鐨勶紝Java鍒╃敤澶氱嚎紼嬩嬌鏁翠釜緋葷粺鎴愪負寮傛ョ郴緇熴侸ava涓鐨勭嚎紼嬬敱涓夐儴鍒嗙粍鎴愶紝濡傚浘6.1鎵紺恆
1. 鉶氭嫙鐨凜PU錛屽皝瑁呭湪Java.lang.Thread綾諱腑銆
2. CPU鎵鎵ц岀殑浠g爜錛屼紶閫掔粰Thread綾匯
3. CPU鎵澶勭悊鐨勬暟鎹錛屼紶閫掔粰Thread綾匯
鍥6.1綰跨▼
6. 1. 2 綰跨▼浣(1)
Java鐨勭嚎紼嬫槸閫氳繃Java.lang.Thread綾繪潵瀹炵幇鐨勩傚綋鎴戜滑鐢熸垚涓涓猅hread綾葷殑瀵硅薄涔嬪悗,涓涓鏂扮殑綰跨▼灝變駭鐢熶簡銆
姝ょ嚎紼嬪疄渚嬭〃紺篔ava瑙i噴鍣ㄤ腑鐨勭湡姝g殑綰跨▼錛岄氳繃瀹冨彲浠ュ惎鍔ㄧ嚎紼嬨佺粓姝㈢嚎紼嬨佺嚎紼嬫寕璧風瓑錛屾瘡涓綰跨▼閮芥槸閫氳繃綾籘hread鍦↗ava鐨勮蔣浠跺寘Java.lang涓瀹氫箟錛屽畠鐨勬瀯閫犳柟娉曚負錛
public Thread 錛圱hreadGroup group錛孯unnable target錛孲tring name錛夛紱
鍏朵腑錛実roup 鎸囨槑璇ョ嚎紼嬫墍灞炵殑綰跨▼緇勶紱target瀹為檯鎵ц岀嚎紼嬩綋鐨勭洰鏍囧硅薄錛屽畠蹇呴』瀹炵幇鎺ュ彛Runnable錛 name涓虹嚎紼嬪悕銆侸ava涓鐨勬瘡涓綰跨▼閮芥湁鑷宸辯殑鍚嶇О錛孞ava鎻愪緵浜嗕笉鍚孴hread綾繪瀯閫犲櫒錛屽厑璁哥粰綰跨▼鎸囧畾鍚嶇О銆傚傛灉name涓簄ull鏃訛紝鍒橨ava鑷鍔ㄦ彁渚涘敮涓鐨勫悕縐般
褰撲笂榪版瀯閫犳柟娉曠殑鏌愪釜鍙傛暟涓簄ull鏃訛紝鎴戜滑鍙寰楀埌涓嬮潰鐨勫嚑涓鏋勯犳柟娉曪細
public Thread 錛堬級錛
public Thread 錛圧unnable target錛夛紱
public Thread 錛圧unnable target錛孲tring name錛夛紱
public Thread 錛圫tring name錛夛紱
public Thread 錛圱hreadGroup group錛孯unnable target錛夛紱
public Thread 錛圱hreadGroup group錛孲tring name錛夛紱
涓涓綾誨0鏄庡疄鐜癛unnable鎺ュ彛灝卞彲浠ュ厖褰撶嚎紼嬩綋錛屽湪鎺ュ彛Runnable涓鍙瀹氫箟浜嗕竴涓鏂規硶 run錛堬級錛
public void run錛堬級錛
浠諱綍瀹炵幇鎺ュ彛Runnable鐨勫硅薄閮藉彲浠ヤ綔涓轟竴涓綰跨▼鐨勭洰鏍囧硅薄錛岀被Thread鏈韜涔熷疄鐜頒簡鎺ュ彛Runnable錛屽洜姝ゆ垜浠鍙浠ラ氳繃涓ょ嶆柟娉曞疄鐜扮嚎紼嬩綋銆
錛堜竴錛夊畾涔変竴涓綰跨▼綾伙紝瀹冪戶鎵跨嚎紼嬬被Thread騫墮噸鍐欏叾涓鐨勬柟娉 run錛堬級錛岃繖鏃跺湪鍒濆嬪寲榪欎釜綾葷殑瀹炰緥鏃訛紝鐩鏍噒arget鍙涓簄ull錛岃〃紺虹敱榪欎釜瀹炰緥瀵規潵鎵ц岀嚎紼嬩綋銆傜敱浜嶫ava鍙鏀鎸佸崟閲嶇戶鎵匡紝鐢ㄨ繖縐嶆柟娉曞畾涔夌殑綾諱笉鑳藉啀緇ф壙鍏跺畠鐖剁被銆
錛堜簩錛夋彁渚涗竴涓瀹炵幇鎺ュ彛Runnable鐨勭被浣滀負涓涓綰跨▼鐨勭洰鏍囧硅薄錛屽湪鍒濆嬪寲涓涓猅hread綾繪垨鑰匱hread瀛愮被鐨勭嚎紼嬪硅薄鏃訛紝鎶婄洰鏍囧硅薄浼犻掔粰榪欎釜綰跨▼瀹炰緥錛岀敱璇ョ洰鏍囧硅薄鎻愪緵綰跨▼浣 run錛堬級銆傝繖鏃訛紝瀹炵幇鎺ュ彛Runnable鐨勭被浠嶇劧鍙浠ョ戶鎵垮叾瀹冪埗綾匯
姣忎釜綰跨▼閮芥槸閫氳繃鏌愪釜鐗瑰畾Thread瀵硅薄鐨勬柟娉時un( )鏉ュ畬鎴愬叾鎿嶄綔鐨勶紝鏂規硶run( )縐頒負綰跨▼浣撱傚浘6.2琛ㄧず浜咼ava綰跨▼鐨勪笉鍚岀姸鎬佷互鍙婄姸鎬佷箣闂磋漿鎹㈡墍璋冪敤鐨勬柟娉曘
鍥6.2 綰跨▼鐨勭姸鎬
1. 鍒涘緩鐘舵(new Thread)
鎵ц屼笅鍒楄鍙ユ椂錛岀嚎紼嬪氨澶勪簬鍒涘緩鐘舵侊細
Thread myThread = new MyThreadClass( );
褰撲竴涓綰跨▼澶勪簬鍒涘緩鐘舵佹椂錛屽畠浠呬粎鏄涓涓絀虹殑綰跨▼瀵硅薄錛岀郴緇熶笉涓哄畠鍒嗛厤璧勬簮銆
2. 鍙榪愯岀姸鎬( Runnable )
Thread myThread = new MyThreadClass( );
myThread.start( );
褰撲竴涓綰跨▼澶勪簬鍙榪愯岀姸鎬佹椂錛岀郴緇熶負榪欎釜綰跨▼鍒嗛厤浜嗗畠闇鐨勭郴緇熻祫婧愶紝瀹夋帓鍏惰繍琛屽苟璋冪敤綰跨▼榪愯屾柟娉曪紝榪欐牱灝變嬌寰楄ョ嚎紼嬪勪簬鍙榪愯( Runnable )鐘舵併傞渶瑕佹敞鎰忕殑鏄榪欎竴鐘舵佸苟涓嶆槸榪愯屼腑鐘舵侊紙Running )錛屽洜涓虹嚎紼嬩篃璁稿疄闄呬笂騫舵湭鐪熸h繍琛屻傜敱浜庡緢澶氳$畻鏈洪兘鏄鍗曞勭悊鍣ㄧ殑錛屾墍浠ヨ佸湪鍚屼竴鏃跺埢榪愯屾墍鏈夌殑澶勪簬鍙榪愯岀姸鎬佺殑綰跨▼鏄涓嶅彲鑳界殑錛孞ava鐨勮繍琛岀郴緇熷繀欏誨疄鐜拌皟搴︽潵淇濊瘉榪欎簺綰跨▼鍏變韓澶勭悊鍣ㄣ
3. 涓嶅彲榪愯岀姸鎬侊紙Not Runnable錛
榪涘叆涓嶅彲榪愯岀姸鎬佺殑鍘熷洜鏈夊備笅鍑犳潯錛
1) 璋冪敤浜唖leep錛堬級鏂規硶;
2) 璋冪敤浜唖uspend錛堬級鏂規硶;
3) 涓虹瓑鍊欎竴涓鏉′歡鍙橀噺錛岀嚎紼嬭皟鐢╳ait錛堬級鏂規硶;
4) 杈撳叆杈撳嚭嫻佷腑鍙戠敓綰跨▼闃誨;
涓嶅彲榪愯岀姸鎬佷篃縐頒負闃誨炵姸鎬侊紙Blocked錛夈傚洜涓烘煇縐嶅師鍥狅紙杈撳叆/杈撳嚭銆佺瓑寰呮秷鎮鎴栧叾瀹冮樆濉炴儏鍐碉級錛岀郴緇熶笉鑳芥墽琛岀嚎紼嬬殑鐘舵併傝繖鏃跺嵆浣垮勭悊鍣ㄧ┖闂詫紝涔熶笉鑳芥墽琛岃ョ嚎紼嬨
4. 姝諱骸鐘舵侊紙Dead錛
綰跨▼鐨勭粓姝涓鑸鍙閫氳繃涓ょ嶆柟娉曞疄鐜幫細鑷鐒舵挙娑堬紙綰跨▼鎵ц屽畬錛夋垨鏄琚鍋滄錛堣皟鐢╯top()鏂規硶錛夈傜洰鍓嶄笉鎺ㄨ崘閫氳繃璋冪敤stop()鏉ョ粓姝㈢嚎紼嬬殑鎵ц岋紝鑰屾槸璁╃嚎紼嬫墽琛屽畬銆
http://www.bc-cn.net/Article/kfyy/java/jc/200410/83.html