国产另类ts人妖一区二区_欧美肥老太做爰视频_快穿高h肉_国产欧美综合在线

當前位置: 首頁 / 技術干貨 / 正文
好程序員Java培訓分享Java多線程并發

2020-07-14

Java培訓 好程序員

  好程序員Java培訓分享Java多線程并發,1 Java 線程實現/創建方式

  繼承 Thread

  Thread 類本質上是實現了 Runnable 接口的一個實例,代表一個線程的實例。啟動線程的唯一方法就是通過 Thread 類的 start()實例方法。start()方法是一個 native 方法,它將啟動一個新線程,并執行 run()方法。

QQ截圖20190505135426

 

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();

 

} }

 

ExecutorServiceCallableFuture 有返回值線程

 

有返回值的任務必須實現 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 框架實現的,該框架中用到了 ExecutorExecutorsExecutorServiceThreadPoolExecutor Callable FutureFutureTask 這幾個類。

 

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 時,多余的空閑線程的存活時間,即多次時間內會被銷毀。

 

unitkeepAliveTime 的單位。

 

workQueue:任務隊列,被提交但尚未被執行的任務。

 

threadFactory:線程工廠,用于創建線程,一般用默認的即可。

 

handler:拒絕策略,當任務太多來不及處理,如何拒絕任務。

 

拒絕策略線程池中的線程已經用完了,無法繼續為新任務服務,同時,等待隊列也已經排滿了,再也塞不下新任務了。這時候我們就需要拒絕策略機制合理的處理這個問題。

 

JDK 內置的拒絕策略如下:

 

AbortPolicy :直接拋出異常,阻止系統正常運行。

 

CallerRunsPolicy :只要線程池未關閉,該策略直接在調用者線程中,運行當前被丟棄的任務。顯然這樣做不會真的丟棄任務,但是,任務提交線程的性能極有可能會急劇下降。

 

DiscardOldestPolicy :丟棄最老的一個請求,也就是即將被執行的一個任務,并嘗試再次提交當前任務。

 

DiscardPolicy :該策略默默地丟棄無法處理的任務,不予任何處理。如果允許任務丟失,這是zuihao的一種方案。

 

以上內置拒絕策略均實現了 RejectedExecutionHandler 接口,若以上策略仍無法滿足實際需要,完全可以自己擴展 RejectedExecutionHandler 接口。

 

Java 線程池工作過程(1)線程池剛創建時,里面沒有一個線程。任務隊列是作為參數傳進來的。不過,就算隊列里面有任務,線程池也不會馬上執行它們。

 

(2)當調用 execute() 方法添加一個任務時,線程池會做如下判斷:

 

a) 如果正在運行的線程數量小于 corePoolSize,那么馬上創建線程運行這個任務;

 

b) 如果正在運行的線程數量大于或等于 corePoolSize,那么將這個任務放入隊列;

 

c) 如果這時候隊列滿了,而且正在運行的線程數量小maximumPoolSize,那么還是要創建非核心線程立刻運行這個任務;

 

d) 如果隊列滿了,而且正在運行的線程數量大于或等maximumPoolSize,那么線程池會拋出異常 RejectExecutionException

 

(3)當一個線程完成任務時,它會從隊列中取下一個任務來執行。

 

(4)當一個線程無事可做,超過一定的時間(keepAliveTime)時,線程池會判斷,如果當前運行的線程數大于 corePoolSize,那么這個線程就被停掉。所以線程池的所有任務完成后,它最終會收縮到 corePoolSize 的大小。

好程序員公眾號

  • · 剖析行業發展趨勢
  • · 匯聚企業項目源碼

好程序員開班動態

More+
  • HTML5大前端 <高端班>

    開班時間:2021-04-12(深圳)

    開班盛況

    開班時間:2021-05-17(北京)

    開班盛況
  • 大數據+人工智能 <高端班>

    開班時間:2021-03-22(杭州)

    開班盛況

    開班時間:2021-04-26(北京)

    開班盛況
  • JavaEE分布式開發 <高端班>

    開班時間:2021-05-10(北京)

    開班盛況

    開班時間:2021-02-22(北京)

    開班盛況
  • Python人工智能+數據分析 <高端班>

    開班時間:2021-07-12(北京)

    預約報名

    開班時間:2020-09-21(上海)

    開班盛況
  • 云計算開發 <高端班>

    開班時間:2021-07-12(北京)

    預約報名

    開班時間:2019-07-22(北京)

    開班盛況
IT培訓IT培訓
在線咨詢
IT培訓IT培訓
試聽
IT培訓IT培訓
入學教程
IT培訓IT培訓
立即報名
IT培訓

Copyright 2011-2023 北京千鋒互聯科技有限公司 .All Right 京ICP備12003911號-5 京公網安備 11010802035720號