【多執行緒高併發程式設計】二 實現多執行緒的幾種方式
程式猿學社的GitHub,歡迎Star
https://github.com/ITfqyd/cxyxs
本文已記錄到github,形成對應專題
文章目錄
前言:
上章,我們已經瞭解執行緒的一些基本概念。本文我們來看看多執行緒的應用場景,為什麼要用多執行緒,以及實現一個多執行緒有幾種方式。
1.什麼是多執行緒?
多執行緒是指通過軟體優化和硬體(CPU)的方式,同時併發執行多個執行緒(任務)。更好的執行系統的資源。
例如,社長,很久以前,接到boss的提的一個業務,需要開發一個充電樁管理物聯網管理平臺,實現通過網站,檢視各個充電樁的情況。如果就社長一個人開發,感覺1年搞定都有點難,畢竟社長專注於後端開發,這時社長就跟boss提出,需要增加人馬,招一個前端,一個後端。社長就負責跟硬體對接,每個人負責一塊,各種同步開發。最後,通過社長三人的努力,半年就交差了。這就是多執行緒的好處。多個人,資訊也是共享(一個程式內的多個執行緒,資源是共享在同一個記憶體中)
1.1應用場景
- 網站傳送多個請求,會一一返回結果,也就是很高的使用了多執行緒。如果沒有多執行緒,我們搶票,就得發一個請求後,需要等請求處理完後,才能執行。
- 扣扣聊天介面,如果沒有多執行緒,發一個訊息,需要上一個訊息處理完後,才能處理下一個需求。
- 通過netty解析資料包文,如果沒有多執行緒,1w個執行緒,直接懟進來,我們只能一個個處理,肯定處理不過來,如果沒有多執行緒,解析邏輯也無法和業務邏輯分離開,實現程式的解耦。
2.實現一個多執行緒的常見幾種方式
為了模擬真實的場景,每個執行緒中,都增加了延遲執行的程式碼。
Thread.sleep(1000);
這句程式碼表示休眠1秒鐘,以毫秒為單位。
通過繼承的方式,實現多執行緒(第一種)
package com.cxyxs.two;
import java.util.Date;
/**
* Description:第一種:通過繼承的方式,實現多執行緒
* 轉發請註明來源 程式猿學社 - https://ithub.blog.csdn.net/
* Author: 程式猿學社
* Date: 2020/2/17 21:37
* Modified By:
*/
public class MyThreadExtend extends Thread {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("程式猿學社:社長在開發中,通過繼承的方式實現:" + new Date());
}
}
}
呼叫程式碼
//第一種方式
MyThreadExtend threadExtend = new MyThreadExtend();
threadExtend.start();
- 因為java中是單繼承,所以不推薦通過這種方式實現多執行緒。如果該類已經被繼承,是無法繼承Thread類的。
通過實現runnable介面,實現多執行緒(第二種)
package com.cxyxs.two;
import java.util.Date;
/**
* Description:轉發請註明來源 程式猿學社 - https://ithub.blog.csdn.net/
* Author: 程式猿學社
* Date: 2020/2/17 21:43
* Modified By:
*/
public class MyThreadRunnable implements Runnable{
@Override
public void run() {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("小二在開發中,通過實現Runnable介面方式實現:" + new Date());
}
}
}
呼叫程式碼
//第二種方式
MyThreadRunnable runnable = new MyThreadRunnable();
Thread thread = new Thread(runnable);
thread.start();
匿名內部類實現(第三種)
Runnable方式
//匿名內部類-第一種
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("通過匿名內部類的方式第一種實現!");
}
}).start();
繼承類方式
//匿名內部類-第二種
new Thread(){
@Override
public void run() {
System.out.println("通過匿名內部類的方式第二種實現!");
}
}.start();
通過Callable實現多執行緒(第四種)
public class MyThreadCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
int sum=0;
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
sum+=i;
System.out.println("小王通過實現Callable介面的方式實現:" + new Date());
}
return sum;
}
}
呼叫程式碼
//第四種 通過Callable實現多執行緒
MyThreadCallable callable = new MyThreadCallable();
FutureTask<Integer> result = new FutureTask<Integer>(callable);
new Thread(result).start();
try {
Integer sum = result.get();
System.out.println("計算結果:"+sum);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
- 之前幾種實現多執行緒的方法,需要重寫run方法,啟動多執行緒。而Callable方式實現多執行緒,需要重寫call方法。通過FutureTask包裝器來建立Thread執行緒
- 通過呼叫get方法獲取多執行緒的執行結果。注意,get方法會一直堵塞,沒有返回值,主執行緒會一直等待。
- 應用場景,例如批量大資料的匯出,假設我們要匯出100w資料,需要30s,我們就可以通過分頁,每個執行緒查10w的資料,啟動10個執行緒,來獲取處理結果。這樣就可以通過多執行緒提供查詢的效率。
啟動一個main執行緒,啟動了幾個執行緒
public class ThreadCount {
public static void main(String[] args) {
ThreadGroup group =
Thread.currentThread().getThreadGroup();
int count = group.activeCount();
group.list();
}
}
idea列印
eclipse列印
啟動了2個執行緒,一個主執行緒main,是程式的入口。
還有一個[Monitor Ctrl-Break,這是IDEA特有的監控執行緒。正確的列印應該是gc執行緒。通過上面兩張圖,就可以得出這個結論。
多個執行緒進行測試
public class Test {
public static void main(String[] args) {
//第一種方式
MyThreadExtend threadExtend = new MyThreadExtend();
threadExtend.start();
//第二種方式
MyThreadRunnable runnable = new MyThreadRunnable();
Thread thread = new Thread(runnable);
thread.start();
//第三種方式
//匿名內部類-第一種
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("通過匿名內部類的方式第一種實現!");
}
}).start();
//匿名內部類-第二種
new Thread() {
@Override
public void run() {
System.out.println("通過匿名內部類的方式第二種實現!");
}
}.start();
//第四種 通過Callable實現多執行緒
MyThreadCallable callable = new MyThreadCallable();
FutureTask<Integer> result = new FutureTask<Integer>(callable);
new Thread(result).start();
try {
Integer sum = result.get();
System.out.println("計算結果:"+sum);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}
- 通過測試的結果,我們發現,資料是交換執行的,如果是單cpu,每次只能執行一個通道,就算用多執行緒的方式實現,每次也是交替執行。只是計算機執行速度很快,我們看不出什麼區別。說到這裡,就有社友提出疑問,單cpu,還有必要用多執行緒嗎?
就算是單cpu,利用多執行緒也有很多好處。讓我們可以減少沒必要的等待,更好的利用資源。 - 如果是多cpu,就可以同時併發執行多個任務,大大的提高執行效率。
相關文章
- Java高併發與多執行緒(二)-----執行緒的實現方式Java執行緒
- 多執行緒與高併發(二)執行緒安全執行緒
- Python併發程式設計之建立多執行緒的幾種方法(二)Python程式設計執行緒
- Java建立多執行緒的幾種方式實現Java執行緒
- 多執行緒與高併發(一)多執行緒入門執行緒
- 3種方式實現python多執行緒併發處理Python執行緒
- 多執行緒併發程式設計“鎖”事執行緒程式設計
- Java實現多執行緒的三種方式Java執行緒
- 多執行緒程式設計基礎(二)-- 執行緒池的使用執行緒程式設計
- 併發程式設計 建立執行緒的三種方式程式設計執行緒
- 多執行緒實現多工二執行緒
- Java多執行緒實現方式Java執行緒
- 用多執行緒,實現併發,TCP執行緒TCP
- 多執行緒併發篇——如何停止執行緒執行緒
- 多執行緒高併發程式設計(10) -- ConcurrentHashMap原始碼分析執行緒程式設計HashMap原始碼
- 關於多執行緒的兩種實現方式執行緒
- 使用Java實現多執行緒程式設計Java執行緒程式設計
- 【多執行緒與高併發】- 執行緒基礎與狀態執行緒
- 併發程式設計之多執行緒執行緒安全程式設計執行緒
- 【java】【多執行緒】建立執行緒的兩種常用方式(2)Java執行緒
- c# 多執行緒的幾種方式 【轉載】C#執行緒
- C#多執行緒程式設計實戰1.1建立執行緒C#執行緒程式設計
- JAVA多執行緒併發Java執行緒
- [短文速讀 -5] 多執行緒程式設計引子:程式、執行緒、執行緒安全執行緒程式設計
- 併發與多執行緒之執行緒安全篇執行緒
- 多執行緒程式設計基礎(一)-- 執行緒的使用執行緒程式設計
- 【java多執行緒】(二)執行緒停止Java執行緒
- 多執行緒高併發程式設計(8) -- Fork/Join原始碼分析執行緒程式設計原始碼
- 多執行緒高併發程式設計(3) -- ReentrantLock原始碼分析AQS執行緒程式設計ReentrantLock原始碼AQS
- python 多執行緒程式設計Python執行緒程式設計
- JavaScript多執行緒程式設計JavaScript執行緒程式設計
- Python多執行緒程式設計Python執行緒程式設計
- 面試-實現多執行緒的方式面試執行緒
- 執行緒以及多執行緒,多程式的選擇執行緒
- 多執行緒程式設計1-定義理解與三種實現方式執行緒程式設計
- java 多執行緒之使用 interrupt 停止執行緒的幾種方法Java執行緒
- iOS開發-多執行緒程式設計iOS執行緒程式設計
- 多執行緒(二)執行緒