iT邦幫忙

2022 iThome 鐵人賽

DAY 16
0
Software Development

大學耍廢的我要學Java翻身系列 第 16

Day16: Java的多main宇宙(下)

  • 分享至 

  • xImage
  •  

多執行緒常用方法

yield()

它會將目前在執行的執行緒使用權限讓出來,交給後續的執行緒繼續執行
會讓執行緒停在runnable等排班器呼叫它執行running

// Main.java
public class Main {
    public static void main(String[] args){
        System.out.println("main Thread start");
//
        Thread thread1 = new Thread(new TestThread("thread1"));
        Thread thread2 = new Thread(new TestThread("thread2"));
        Thread thread3 = new Thread(new TestThread("thread3"));

        thread1.start();
        thread2.start();
        thread3.start();
        System.out.println("main thread end");
    }
}
// TestThread.java
public class TestThread implements Runnable {
    private String name;

    public TestThread(String name){
        this.name = name;
    }
    public void run(){
        System.out.println(name + " start");
        if ("thread1".equals(name))
            Thread.yield();
        System.out.println(name + " Running");
        System.out.println(name + " end");
    }
}

sleep()

可以指定停止的時間(以毫秒為單位),可以指定執行緒等待多久,時間到了就會開始繼續進行
會讓執行緒停在block狀態,直到時間到了以後,才可以進到runnable

// Main.java
public class Main {
    public static void main(String[] args){
        System.out.println("main Thread start");
//
        Thread thread1 = new Thread(new TestThread("thread1"));
        Thread thread2 = new Thread(new TestThread("thread2"));
        Thread thread3 = new Thread(new TestThread("thread3"));

        thread1.start();
        thread2.start();
        thread3.start();
        System.out.println("main thread end");
    }
}
// TestThread.java
public class TestThread implements Runnable {
    private String name;

    public TestThread(String name){
        this.name = name;
    }
    public void run(){
        System.out.println(name + " start");
        if ("thread1".equals(name)) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        System.out.println(name + " Running");
        System.out.println(name + " end");
    }
}

可以看到thread1第一個開始,但是卻是最後一個結束

join

可以讓其他的執行緒先執行完它再去接著執行,它必須要等到插隊的執行緒執行完,才可接續執行

// Main.java
public class Main {
    public static void main(String[] args){
        System.out.println("main Thread start");

        Thread thread1 = new Thread(new TestThread("thread1"));

        thread1.start();
        
        System.out.println("main thread end");
    }
}
// TestThread.java
public class TestThread implements Runnable {
    private String name;

    public TestThread(String name){
        this.name = name;
    }
    public void run(){
        System.out.println(name + " start");
        if ("thread1".equals(name)) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
        System.out.println(name + " Running");
        System.out.println(name + " end");
    }
}

thread1會晚一秒才開始執行,所以我們嘗試加入join()

// Main.java
public class Main {
    public static void main(String[] args){
        System.out.println("main Thread start");

        Thread thread1 = new Thread(new TestThread("thread1"));

        thread1.start();
        try {
            thread1.join();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }

        System.out.println("main thread end");
    }
}

加入join之後,我們的main方法就會等thread1結束才結束

同步(synchronized)

多執行緒在使用同一個資料時會出現資料不一致的狀況
因為多執行緒的執行時間不一定,所以問題不一定會發生,但還是有機會發生
很多執行緒一起在共用一個物件的時候,有人會塞入資料,有人會讀取資料,這時會變成a執行緒塞入的資料變成b執行緒在使用

synchronized用法

在方法加入synchronized這個方法在同一時間只能有一個執行緒使用
我們也能去同步化區塊synchronized(this){...}
另外有一個觀念就是物件的鎖定lock,每一個物件都有一個lock,我們的執行緒要取得lock才能夠執行synchronized裡面的內容

必須在同步化的方法或區塊呼叫的方法

wait(時間參數)、notify()

執行緒進入物件等待池等待,等時間到了或是呼叫了notify()

// Main.java
public class Main {
    public static void main(String[] args){
        System.out.println("main Thread start");
//
        Thread thread1 = new Thread(new TestThread("thread1"));
        Thread thread2 = new Thread(new TestThread("thread2"));
        Thread thread3 = new Thread(new TestThread("thread3"));

        thread1.start();
        thread2.start();
        thread3.start();
        System.out.println("main thread end");
    }
}
// TestThread.java
public class TestThread implements Runnable {
    private String name;

    public TestThread(String name){
        this.name = name;
    }
    public void run(){
        synchronized (this){
            try {
                wait(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
            if ("thread2".equals(name))
                notify();
            System.out.println(name + " start");
            System.out.println(name + " Running");
            System.out.println(name + " end");
        }
    }
}

上一篇
Day15: Java的多main宇宙(上)
下一篇
Day17: Java的視窗--Swing基礎介紹
系列文
大學耍廢的我要學Java翻身30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言