Java多執行緒詳解(一)我與多執行緒的第一次接觸
阿新 • • 發佈:2021-11-26
Java多執行緒詳解
執行緒簡介
執行緒實現(重點)
執行緒狀態
執行緒同步(重點)
執行緒通訊問題
高階主題
多工
- 現實中太多這樣同時做多見事情的例子了,看起來十多個任務都在做,其實本質上我們的大腦在同一時間依舊之作了一件事情。
多執行緒
-
原來是一條路,慢慢因為車太多了,道路堵塞,效率極低。
為了題號使用的效率,能夠充分利用到了,於是加了多個車道。
從此,媽媽再也不用但是道路堵塞了。
-
說說你們的多執行緒例子(生活,遊戲,程式設計)
普通方法呼叫多執行緒
程式.程序.執行緒
Process與Thread
-
說起程序,就不得不說下程式。程式是指令和資料的有序集合,其本身沒有任何執行的含義,是一個靜態的概念。
-
而程序則是執行程式的一次執行過程,他是一個動態的概念,是系統資源分配的單位。
-
通常在一個程序中可以包換若干個執行緒,當然一個程序中至少有一個執行緒,不然沒有存在的意義。執行緒是CPU排程和執行的單位。
-
注意:很多多執行緒是模擬出來的,真正的多執行緒是指有多個CPU,即多核,如伺服器。如果是模擬出來的多執行緒,即在一個CPU的情況系啊,在同一個時間點,CPU只能執行一個程式碼,因為切換的很快,所以就有同時執行的錯覺。
本章核心概念
- 執行緒就是獨立的執行路徑;
- 在程式執行時,即使沒有自己建立執行緒,後臺也會有多個執行緒,如主執行緒,gc執行緒;
- main()稱之為主執行緒,位系統的入口,用於執行整個程式;
- 在一個程序中,如果開闢了多個執行緒,執行緒的執行排程器安排排程,排程器是與作業系統緊密相關的,先後順序是不能人為干預的。
- 對同一份資源操作時,會存在資源搶奪的問題,需要加入併發控制;
- 執行緒會帶來額外的開銷,如CPU排程時間,併發控制開銷。
- 每個執行緒在自己的工作記憶體互動,記憶體控制不當會造成資料不一致。
執行緒建立
Thread、Runnable、Callable
三種建立方式
Thread
(學習提示:檢視JDK幫助文件)
- 自定義執行緒類繼承Thread類
- 重寫run()方法,編寫執行緒執行器
- 建立執行緒物件,呼叫start()方法啟動執行緒
package com.xiancheng.demo01; //常見執行緒方式一:繼承Thread類,重寫run()方法,呼叫start()開啟執行緒 public class TestThread1 extends Thread{ @Override public void run() { //run方法執行緒體 for (int i = 0; i < 20; i++) { System.out.println("我在看程式碼---"+i); } } public static void main(String[] args) { //main執行緒,主執行緒 //建立一個執行緒物件 TestThread1 testThread1 = new TestThread1(); //呼叫start()方法開啟現執行緒 testThread1.start(); for (int i = 0; i < 20; i++) { System.out.println("我在學習多執行緒--"+i); } } }
- 總結:注意,執行緒開清不一定立即執行,由CPU排程執行
案例:下載圖片
package com.xiancheng.demo01;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
//聯絡TestThread,實現多執行緒同步下載圖片
public class TestThread2 extends Thread{
private String url;//網路圖片地址
private String name;//儲存檔名
public TestThread2(String url,String name){
this.url = url;
this.name = name;
}
@Override
public void run() {
WebDownloader webDownloader = new WebDownloader();
webDownloader.downloader(url,name);
System.out.println("下載了檔名為:"+name);
}
public static void main(String[] args){
TestThread2 testThread1 = new TestThread2("https://imgoss.douyucdn.cn/bj/yuba/default/2019/12/20/201912200221045779841615885.jpg","1.jpg");
TestThread2 testThread2 = new TestThread2("https://imgoss.douyucdn.cn/bj/yuba/default/2021/03/26/202103262200428765268485985.jpg","2.jpg");
TestThread2 testThread3 = new TestThread2("https://img.douyucdn.cn/data/yuba/default/2019/08/18/201908182138163129577786480.200x0.jpg","3.jpg");
testThread1.start();
testThread2.start();
testThread3.start();
}
}
//下載器
class WebDownloader{
//下載方法
public void downloader(String url, String name){
try {
FileUtils.copyURLToFile(new URL(url),new File(name));
} catch (IOException e) {
e.printStackTrace();
System.out.println("IO異常,downloader方法出現問題");
}
}
}
- 執行緒是同時執行的
實現Runnable
- 定義MyRunable類實現Runable介面
- 實現run()方法,編寫執行緒執行體
- 建立執行緒物件,呼叫start()方法啟動執行緒
package com.xiancheng.demo01;
//建立執行緒方式2:實現runnable方法,重寫run()方法,呼叫start開啟執行緒
//總結:注意,執行緒開啟不指定立即執行,由CPU排程執行
public class TestThread3 implements Runnable{
@Override
public void run() {
//run方法執行緒體
for (int i = 0; i < 1000; i++) {
System.out.println("我在看程式碼---"+i);
}
}
public static void main(String[] args) {
//建立runnable介面的實現類物件
TestThread3 testThread3 = new TestThread3();
//建立執行緒物件,通過執行緒物件來開啟我們的執行緒,代理
//Thread thread = new Thread(testThread3);
//thread.start();
//簡寫
new Thread(testThread3).start();
for (int i = 0; i < 1000; i++) {
System.out.println("我在學習多執行緒--"+i);
}
}
}
用Runna介面實現圖片下載
package com.xiancheng.demo01;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
//練習TestThread,實現多執行緒同步下載圖片
public class TestThread2 implements Runnable{
private String url;//網路圖片地址
private String name;//儲存檔名
public TestThread2(String url,String name){
this.url = url;
this.name = name;
}
@Override
public void run() {
WebDownloader webDownloader = new WebDownloader();
webDownloader.downloader(url,name);
System.out.println("下載了檔名為:"+name);
}
public static void main(String[] args){
TestThread2 testThread1 = new TestThread2("https://imgoss.douyucdn.cn/bj/yuba/default/2019/12/20/201912200221045779841615885.jpg","1.jpg");
TestThread2 testThread2 = new TestThread2("https://imgoss.douyucdn.cn/bj/yuba/default/2021/03/26/202103262200428765268485985.jpg","2.jpg");
TestThread2 testThread3 = new TestThread2("https://img.douyucdn.cn/data/yuba/default/2019/08/18/201908182138163129577786480.200x0.jpg","3.jpg");
new Thread(testThread1).start();
new Thread(testThread2).start();
new Thread(testThread3).start();
}
}
//下載器
class WebDownloader{
//下載方法
public void downloader(String url, String name){
try {
FileUtils.copyURLToFile(new URL(url),new File(name));
} catch (IOException e) {
e.printStackTrace();
System.out.println("IO異常,downloader方法出現問題");
}
}
}
小結
-
繼承Thread類
- 子類繼承Thread類具備多執行緒能力
- 啟動執行緒:子類物件.start
- 不建議使用:避免OPP單執行緒繼承侷限性
-
實現Runnable介面
- 實現介面Runnale具有多執行緒能力
- 遞送執行緒:傳入目標物件+Thread物件.start()
- 推薦使用:避免單繼承侷限性,靈活方便,方便同一個物件被多個執行緒使用
)