中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么實現Java多線程并發

發布時間:2021-11-01 10:21:35 來源:億速云 閱讀:268 作者:iii 欄目:編程語言

這篇文章主要介紹“怎么實現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多線程并發”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

林甸县| 黄龙县| 六枝特区| 南阳市| 昌邑市| 乳山市| 霍州市| 屏山县| 凌源市| 梧州市| 鄯善县| 丽水市| 宣汉县| 湾仔区| 杨浦区| 镇平县| 宝丰县| 安乡县| 罗甸县| 阜康市| 邯郸市| 健康| 本溪市| 嘉荫县| 太仆寺旗| 鄂尔多斯市| 阳高县| 库尔勒市| 阿图什市| 平果县| 长春市| 博乐市| 双峰县| 内丘县| 扎囊县| 龙游县| 沾益县| 玉山县| 印江| 木兰县| 璧山县|