1. 程式人生 > 其它 >Java多執行緒詳解(一)我與多執行緒的第一次接觸

Java多執行緒詳解(一)我與多執行緒的第一次接觸

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()
    • 推薦使用:避免單繼承侷限性,靈活方便,方便同一個物件被多個執行緒使用
      )