您好,登錄后才能下訂單哦!
這篇文章主要介紹“怎么實現Java多線程并發”,在日常操作中,相信很多人在怎么實現Java多線程并發問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”怎么實現Java多線程并發”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!
繼承 Thread 類
Thread 類本質上是實現了 Runnable 接口的一個實例,代表一個線程的實例。啟動線程的唯一方法就是通過 Thread 類的 start()實例方法。start()方法是一個 native 方法,它將啟動一個新線程,并執行 run()方法。
public class MyThread extends Thread {
public void run() {
System.out.println("MyThread.run()");
} }
MyThread myThread1 = new MyThread();
myThread1.start();
實現 Runnable 接口
如果自己的類已經 extends 另一個類,就無法直接 extends Thread,此時,可以實現一個Runnable 接口。
public class MyThread extends OtherClass implements Runnable {
public void run() {
System.out.println("MyThread.run()");
} } //啟動
MyThreadMyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();
target.run()public void run() {
if (target != null) {
target.run();
} }
ExecutorService、Callable、Future 有返回值線程
有返回值的任務必須實現 Callable 接口,類似的,無返回值的任務必須 Runnable 接口。執行Callable 任務后,可以獲取一個 Future 的對象,在該對象上調用 get 就可以獲取到 Callable 任務返回的 Object 了,再結合線程池接口 ExecutorService 就可以實現傳說中有返回結果的多線程了。
//創建一個線程池
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); list.add(f);
} // 關閉線程池pool.shutdown();
// 獲取所有并發任務的運行結果for (Future f : list) {
// 從 Future 對象上獲取任務的返回值,并輸出到控制臺System.out.println("res:" + f.get().toString());
}
基于線程池的方式
線程和數據庫連接這些資源都是非常寶貴的資源。如果每次需要的時候創建,不需要的時候銷毀,是非常浪費資源的。那么我們就可以使用緩存的策略,也就是使用線程池。
// 創建線程池ExecutorService threadPool = Executors.newFixedThreadPool(10);
while(true) { threadPool.execute(new Runnable() {
// 提交多個線程執行 @Override public void run() {
System.out.println(Thread.currentThread().getName() + " is running ..");
try {
Thread.sleep(3000);
}
catch (InterruptedException e) {
e.printStackTrace();
} } }); }}
2 同步鎖與死鎖
同步鎖當多個線程同時訪問同一個數據時,很容易出現問題。為了避免這種情況出現,我們要保證線程同步互斥,就是指并發執行的多個線程,在同一時間內只允許一個線程訪問共享數據。Java中可以使用synchronized關鍵字來取得一個對象的同步鎖。
死鎖何為死鎖,就是多個線程同時被阻塞,它們中的一個或者全部都在等待某個資源被釋放。
3 線程池原理
線程池做的工作主要是控制運行的線程的數量,處理過程中將任務放入隊列,然后在線程創建后啟動這些任務,如果線程數量超過了最大數量超出數量的線程排隊等候,等其它線程執行完畢,再從隊列中取出任務來執行。主要特點為:線程復用;控制最大并發數;管理線程。
線程復用一個Thread的類都有一個start方法。當調用start啟動線程時Java虛擬機會調用該類的 run 方法。那么該類的 run() 方法中就是調用了 Runnable 對象的 run() 方法。我們可以繼承重寫 Thread 類,在其 start 方法中添加不斷循環調用傳遞過來的 Runnable 對象。這就是線程池的實現原理。循環方法中不斷獲取 Runnable 是用 Queue 實現的,在獲取下一個 Runnable 之前可以是阻塞的。
線程池的組成一般的線程池主要分為以下 4 個組成部分:
(1)線程池管理器:用于創建并管理線程池。(2)工作線程:線程池中的線程。(3)任務接口:每個任務必須實現的接口,用于工作線程調度其運行。(4)任務隊列:用于存放待處理的任務,提供一種緩沖機制。
Java 中的線程池是通過 Executor 框架實現的,該框架中用到了 Executor,Executors,ExecutorService,ThreadPoolExecutor ,Callable 和 Future、FutureTask 這幾個類。
ThreadPoolExecutor 的構造方法如下:
public ThreadPoolExecutor(int corePoolSize,int maximumPoolSize, long keepAliveTime,TimeUnit unit, BlockingQueue<Runnable> workQueue) {this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,Executors.defaultThreadFactory(), defaultHandler);}
corePoolSize:指定了線程池中的線程數量。
maximumPoolSize:指定了線程池中的最大線程數量。
keepAliveTime:當前線程池數量超過 corePoolSize 時,多余的空閑線程的存活時間,即多次時間內會被銷毀。
unit:keepAliveTime 的單位。
workQueue:任務隊列,被提交但尚未被執行的任務。
threadFactory:線程工廠,用于創建線程,一般用默認的即可。
handler:拒絕策略,當任務太多來不及處理,如何拒絕任務。
拒絕策略線程池中的線程已經用完了,無法繼續為新任務服務,同時,等待隊列也已經排滿了,再也塞不下新任務了。這時候我們就需要拒絕策略機制合理的處理這個問題。
JDK 內置的拒絕策略如下:
AbortPolicy :直接拋出異常,阻止系統正常運行。
CallerRunsPolicy :只要線程池未關閉,該策略直接在調用者線程中,運行當前被丟棄的任務。顯然這樣做不會真的丟棄任務,但是,任務提交線程的性能極有可能會急劇下降。
DiscardOldestPolicy :丟棄最老的一個請求,也就是即將被執行的一個任務,并嘗試再次提交當前任務。
DiscardPolicy :該策略默默地丟棄無法處理的任務,不予任何處理。如果允許任務丟失,這是最好的一種方案。
以上內置拒絕策略均實現了 RejectedExecutionHandler 接口,若以上策略仍無法滿足實際需要,完全可以自己擴展 RejectedExecutionHandler 接口。
Java 線程池工作過程(1)線程池剛創建時,里面沒有一個線程。任務隊列是作為參數傳進來的。不過,就算隊列里面有任務,線程池也不會馬上執行它們。
(2)當調用 execute() 方法添加一個任務時,線程池會做如下判斷:
a) 如果正在運行的線程數量小于 corePoolSize,那么馬上創建線程運行這個任務;
b) 如果正在運行的線程數量大于或等于 corePoolSize,那么將這個任務放入隊列;
c) 如果這時候隊列滿了,而且正在運行的線程數量小maximumPoolSize,那么還是要創建非核心線程立刻運行這個任務;
d) 如果隊列滿了,而且正在運行的線程數量大于或等maximumPoolSize,那么線程池會拋出異常 RejectExecutionException。
(3)當一個線程完成任務時,它會從隊列中取下一個任務來執行。
(4)當一個線程無事可做,超過一定的時間(keepAliveTime)時,線程池會判斷,如果當前運行的線程數大于 corePoolSize,那么這個線程就被停掉。所以線程池的所有任務完成后,它最終會收縮到 corePoolSize 的大小。
到此,關于“怎么實現Java多線程并發”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。