<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
Java多執行緒實現方式主要有四種:
① 繼承Thread類、實現Runnable介面
② 實現Callable介面通過FutureTask包裝器來建立Thread執行緒
③ 使用ExecutorService、Callable
④ Future實現有返回結果的多執行緒
其中前兩種方式執行緒執行完後都沒有返回值,後兩種是帶返回值的。
Thread類本質上是實現了Runnable介面的一個範例,代表一個執行緒的範例。啟動執行緒的唯一方法就是通過Thread類的start()實體方法。start()方法是一個native方法,它將啟動一個新執行緒,並執行run()方法。這種方式實現多執行緒很簡單,通過自己的類直接extend Thread,並複寫run()方法,就可以啟動新執行緒並執行自己定義的run()方法。例如:
public class MyThread extends Thread { public void run() { System.out.println("MyThread.run()"); } } MyThread myThread1 = new MyThread(); MyThread myThread2 = new MyThread(); myThread1.start(); myThread2.start();
如果自己的類已經extends另一個類,就無法直接extends Thread,此時,可以實現一個Runnable介面,如下:
public class MyThread extends OtherClass implements Runnable { public void run() { System.out.println("MyThread.run()"); } }
為了啟動MyThread,需要首先範例化一個Thread,並傳入自己的MyThread範例:
MyThread myThread = new MyThread(); Thread thread = new Thread(myThread); thread.start();
事實上,當傳入一個Runnable target引數給Thread後,Thread的run()方法就會呼叫target.run(),參考JDK原始碼:
public void run() { if (target != null) { target.run(); } }
通過FutureTask包裝器來建立Thread執行緒
Callable介面(也只有一個方法)定義如下:
public interface Callable<V> { V call() throws Exception; } public class SomeCallable<V> extends OtherClass implements Callable<V> { @Override public V call() throws Exception { // TODO Auto-generated method stub return null; } }
Callable<V> oneCallable = new SomeCallable<V>(); //由Callable<Integer>建立一個FutureTask<Integer>物件: FutureTask<V> oneTask = new FutureTask<V>(oneCallable); //註釋:FutureTask<Integer>是一個包裝器,它通過接受Callable<Integer>來建立,它同時實現了Future和Runnable介面。 //由FutureTask<Integer>建立一個Thread物件: Thread oneThread = new Thread(oneTask); oneThread.start(); //至此,一個執行緒就建立完成了。
使用ExecutorService、Callable、Future實現有返回結果的執行緒
ExecutorService、Callable、Future三個介面實際上都是屬於Executor框架。返回結果的執行緒是在JDK1.5中引入的新特徵,有了這種特徵就不需要再為了得到返回值而大費周折了。而且自己實現了也可能漏洞百出。
可返回值的任務必須實現Callable介面。類似的,無返回值的任務必須實現Runnable介面。
執行Callable任務後,可以獲取一個Future的物件,在該物件上呼叫get就可以獲取到Callable任務返回的Object了。
注意:get方法是阻塞的,即:執行緒無返回結果,get方法會一直等待。
再結合執行緒池介面ExecutorService就可以實現傳說中有返回結果的多執行緒了。
下面提供了一個完整的有返回結果的多執行緒測試例子,在JDK1.5下驗證過沒問題可以直接使用。程式碼如下:
import java.util.concurrent.*; import java.util.Date; import java.util.List; import java.util.ArrayList; /** * 有返回值的執行緒 */ @SuppressWarnings("unchecked") public class Test { public static void main(String[] args) throws ExecutionException, InterruptedException { System.out.println("----程式開始執行----"); Date date1 = new Date(); int taskSize = 5; // 建立一個執行緒池 ExecutorService pool = Executors.newFixedThreadPool(taskSize); // 建立多個有返回值的任務 List<Future> list = new ArrayList<Future>(); for (int i = 0; i < taskSize; i++) { Callable c = new MyCallable(i + " "); // 執行任務並獲取Future物件 Future f = pool.submit(c); // System.out.println(">>>" + f.get().toString()); list.add(f); } // 關閉執行緒池 pool.shutdown(); // 獲取所有並行任務的執行結果 for (Future f : list) { // 從Future物件上獲取任務的返回值,並輸出到控制檯 System.out.println(">>>" + f.get().toString()); } Date date2 = new Date(); System.out.println("----程式結束執行----,程式執行時間【" + (date2.getTime() - date1.getTime()) + "毫秒】"); } } class MyCallable implements Callable<Object> { private String taskNum; MyCallable(String taskNum) { this.taskNum = taskNum; } public Object call() throws Exception { System.out.println(">>>" + taskNum + "任務啟動"); Date dateTmp1 = new Date(); Thread.sleep(1000); Date dateTmp2 = new Date(); long time = dateTmp2.getTime() - dateTmp1.getTime(); System.out.println(">>>" + taskNum + "任務終止"); return taskNum + "任務返回執行結果,當前任務時間【" + time + "毫秒】"; } }
主要區別 Runnable 介面 run 方法無返回值;
Callable 介面 call 方法有返回值,支援泛型 Runnable 介面 run 方法只能丟擲執行時異常,且無法捕獲處理;
Callable 介面 call 方 法允許丟擲異常,可以獲取異常資訊
執行緒物件呼叫 run 方法不開啟執行緒。僅是物件呼叫方法。
執行緒物件呼叫 start 開啟執行緒,並讓 jvm 呼叫 run 方法在開啟的執行緒中執行呼叫 start 方法可以啟動執行緒,並且使得執行緒進入就緒狀態,而 run 方法只是 thread 的一 個普通方法,還是在主執行緒中執行。
執行緒相關的基本方法有 wait,notify,notifyAll,sleep,join,yield 等
執行緒等待(wait) 呼叫該方法的執行緒進入 waiting狀態,只有等待另外執行緒的通知或被中斷才會返回,需要注意的是呼叫 wait()方法後,會釋放物件 的鎖。因此,wait 方 法一般用在同步方法或同步程式碼塊中。
執行緒睡眠(sleep) sleep 導致當前執行緒休眠,與 wait 方法不同的是 sleep 不會釋放當前佔 有的鎖,sleep(long)會導致執行緒進入 TIMED-WATING 狀態,而 wait()方法 會導致當前執行緒進入 WATING 狀態.
執行緒讓步(yield) yield 會使當前執行緒讓出 CPU 執行時間片,與其他執行緒一起重新競爭 CPU 時間片。一般情況下,優先順序高的執行緒有更大的可能性成功競爭得到 CPU 時間片,但這又不是絕對的,有的作業系統對 執行緒優先順序並不敏感。
執行緒中斷(interrupt) 中斷一個執行緒,其本意是給這個執行緒一個通知訊號,會影響這個執行緒內部的 一箇中斷標識位。這個執行緒本身並不會因此而改變狀態(如阻塞,終止等)
Join 等待其他執行緒終止 join() 方法,等待其他執行緒終止,在當前執行緒中呼叫一個執行緒的 join() 方 法,則當前執行緒轉為阻塞狀態,回到另一個執行緒結束,當前執行緒再由阻塞狀態變 為就緒狀態,等待 cpu 的寵幸.
執行緒喚醒(notify) Object 類中的 notify() 方法,喚醒在此物件監視器上等待的單個執行緒,如 果所有執行緒都在此物件上等待,則會選擇喚醒其中一個線 程,選擇是任意的,並在對實現做出決定時發生,執行緒通過呼叫其中一個 wait() 方法,在物件的監視 器上等待,直到當前的執行緒放棄此物件上的鎖 定,才能繼續執行被喚醒的執行緒, 被喚醒的執行緒將以常規方式與在該物件上主動同步的其他所有執行緒進行競爭。類 似的方法還有 notifyAll() ,喚醒再 次監視器上等待的所有執行緒。
① 來自不同的類 wait():來自 Object 類; sleep():來自 Thread 類;
② 關於鎖的釋放: wait():在等待的過程中會釋放鎖; sleep():在等待的過程中不會釋放鎖
③ 使用的範圍: wait():必須在同步程式碼塊中使用; sleep():可以在任何地方使用;
④ 是否需要捕獲異常 wait():不需要捕獲異常; sleep():需要捕獲異常;
多執行緒原理:多執行緒是通過並行的方式進行。對於一個CPU它在某個時間點上,只能執行一個程式,即同一時間只能執行一個程序,CPU會不斷地在這些程序之間切換,每個執行緒執行一個時間。因為CPU的執行速度相對我們的感覺實在太快了,雖然CPU在多個程序之間輪換執行,但我們自己感到好像多個程序在同時執行。
CPU會在多個程序之間做著切換,如果我們開啟的程式過多,CPU切換到每一個程序的時間也會變長,我們也會感覺機器執行變慢。所以合理的使用多執行緒可以提高效率,但是大量使用,並不能給我們帶來效率上的提高。
多執行緒技術主要解決處理器單元內多個執行緒執行的問題,它可以顯著減少處理器單元的閒置時間,增加處理器單元的吞吐能力。
到此這篇關於Java詳解實現多執行緒的四種方式總結的文章就介紹到這了,更多相關Java多執行緒內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45