1. 程式人生 > 實用技巧 >Java中的多執行緒學習筆記001:Thread類和Runnable介面

Java中的多執行緒學習筆記001:Thread類和Runnable介面

https://space.bilibili.com/95256449/channel/detail?cid=146244

Java中的多執行緒001

1、繼承Thread類,重寫run方法,建立執行緒物件,呼叫start()方法

package com.stark.study;

//建立執行緒方式一:繼承Thread類,重寫run()方法,呼叫start()開啟執行緒
public class TestThread extends Thread {

    //重寫run方法
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("副執行緒" + i);
        }
    }

    //main執行緒,主執行緒
    public static void main(String[] args) {
        //建立執行緒物件
        TestThread testThread = new TestThread();
        //呼叫start()方法啟動副執行緒
        testThread.start();

        for (int i = 0; i < 1000; i++) {
            System.out.println("主執行緒" + i);
        }
    }
}

2、使用Apache的commons io 和多執行緒下載圖片

package com.stark.study;

import org.apache.commons.io.FileUtils;

import java.io.File;
import java.io.IOException;
import java.net.URL;

//練習Thread,實現多執行緒同步下載圖片
public class TestThread2 extends Thread {
    private String url;//網路地址
    private String name;//儲存的檔名

    public TestThread2(String url,String name) {
        this.url = url;
        this.name = name;
    }

    //重寫run方法
    @Override
    public void run() {
//        super.run();
        WebDownloader webDownloader = new WebDownloader();
        webDownloader.downloader(url,name);
        System.out.println(name + "檔案已下載");
    }

    public static void main(String[] args) {
        TestThread2 t1 = new TestThread2("https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png","picture001.jpg");
        TestThread2 t2 = new TestThread2("https://dss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/topnav/[email protected]","picture002.jpg");
        TestThread2 t3 = new TestThread2("https://dss0.bdstatic.com/5aV1bjqh_Q23odCf/static/superman/img/topnav/[email protected]","picture003.jpg");

        t1.start();
        t2.start();
        t3.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異常,WebDownloader.downloader()方法異常。");
        }
    }
}

3、 建立執行緒的另一種方法是宣告一個實現Runnable介面的類。 該類然後實現run方法。 然後可以分配類的例項,再建立Thread時作為引數傳遞,然後啟動。

package com.stark.study;

//建立執行緒方式2:實現Runnable介面,重寫run方法, 然後可以分配類的例項,再建立Thread時作為引數傳遞,然後啟動。
public class TestThread3 implements Runnable {

    //重寫run方法
    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("副執行緒" + i);
        }
    }

    //main執行緒,主執行緒
    public static void main(String[] args) {
        //建立Runnable介面的實現類物件
        TestThread3 testThread3 = new TestThread3();
        //建立Thread類的物件,將Runnable的實現類物件作為引數傳入,然後啟動執行緒
//        Thread thread = new Thread(testThread3);
//        thread.start();
        new Thread(testThread3).start();

        for (int i = 0; i < 1000; i++) {
            System.out.println("主執行緒" + i);
        }
    }
}

4、 多執行緒操作同一個物件,執行緒不安全,存在併發問題

package com.stark.study;

//多個執行緒同時操作同一個物件
//買火車票的例子

//多個執行緒操作同一個物件時,執行緒不安全,資料紊亂,存在併發問題
public class TestThread4 implements Runnable {
    //票數
    private int ticketNums = 30;

    @Override
    public void run() {
        while (true)
        {
            if (0 >= ticketNums)
            {
                break;
            }
            System.out.println(Thread.currentThread().getName() + "--拿到了第" + ticketNums-- + "票");
            //延時
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void main(String[] args) {
        TestThread4 ticket = new TestThread4();
        //多執行緒操作同一個物件
        new Thread(ticket,"學生").start();
        new Thread(ticket,"老師").start();
        new Thread(ticket,"黃牛").start();
    }
}

5、 龜兔賽跑

package com.stark.study;

public class Race implements Runnable {
    private static String winner;//勝利者
    @Override
    public void run() {
        for (int i = 0; i <= 1000; i++) {

            //判斷比賽是否結束
            boolean flag = gameOver(i);
            if (flag){
                break;
            }

            //模擬兔子休息
            if (Thread.currentThread().getName().equals("兔子") && (i%10 == 0)){
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

            System.out.println(Thread.currentThread().getName() + "--跑了" + i + "步");
        }
    }
    //判斷是否完成比賽
    private boolean gameOver(int steps) {
        //判斷是否有勝利者
        if (null != winner) {
            return true;
        }
        if (steps >= 1000){
            winner = Thread.currentThread().getName();
            System.out.println("Winner is " + winner );
            return true;
        }
        return false;
    }

    public static void main(String[] args) {
        Race race = new Race();

        new Thread(race,"兔子").start();
        new Thread(race,"烏龜").start();
    }
}