Java多線程:5.Thread類和Object類的重要方法

一、重要方法概覽

方法名 說明
Thread sleep() 讓線程等待
join() 等待其他線程執行完畢
yield() 放棄已經獲取到的CPU資源
currentThread() 獲取當前執行線程的引用
start()、run() 啓動線程
interrtupt() 中斷線程
stop()、suspend()、resuem() 已廢棄
Object wait()、notify()、notifyAll() 讓線程暫時休息和喚醒

二、Object類中的wait()、notify()、notifyAll()

1.作用
  • 阻塞階段
    執行wait()後,線程進入阻塞狀態,wait()需要在synchronized的方法中使用。
  • 喚醒階段
    notify()會喚醒某個正在等待鎖的線程,如果有多個線程都在等待鎖,則會選取其中任意一個喚醒。需要在synchronized的方法中使用
    notifyAll()會把所有正在等待的線程全部喚醒,最終哪個線程能獲得鎖,由操作系統決定。
  • 遇到中斷
    線程在阻塞狀態,如果被中斷了,則該線程會拋出中斷異常並釋放鎖。
2.wait()和notify()的演示
/**
 * Object類中的wait()、notify()的基本用法
 */
public class ThreadWaitNotify {

    public static Object object = new Object();

    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(new DoWork1());
        Thread thread2 = new Thread(new DoWork2());

        thread1.start();
        Thread.sleep(1000);
        thread2.start();
    }
}

class DoWork1 implements Runnable{
    @Override
    public void run() {
        synchronized (ThreadWaitNotify.object){
            System.out.println("線程1開始執行");
            try {
                // 釋放鎖,阻塞
                ThreadWaitNotify.object.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("線程1重新獲得鎖");
        }
    }
}

class DoWork2 implements Runnable{
    @Override
    public void run() {
        synchronized (ThreadWaitNotify.object){
            ThreadWaitNotify.object.notify();
            System.out.println("線程2調用notify()");
        }
    }
}

在這裏插入圖片描述
線程1中執行了wait()語句後即線程1進入等待狀態,並且釋放掉了鎖,否則線程2無法進入synchronized的代碼塊。

3.notify()和notifyAll()的演示
/**
 * Object類中的notify()、notifyAll()的基本用法
 * 線程1、線程2阻塞,線程3負責喚醒他們
 */
public class ThreadWaitNotify {

    public static Object resource = new Object();

    public static void main(String[] args) throws InterruptedException {
        DoWork1 doWork = new DoWork1();
        DoWork3 doWork3 = new DoWork3();

        Thread thread1 = new Thread(doWork);
        Thread thread2 = new Thread(doWork);
        Thread thread3 = new Thread(doWork3);

        thread1.start();
        thread2.start();

        Thread.sleep(100);
        thread3.start();
    }
}

class DoWork1 implements Runnable{
    @Override
    public void run() {
        synchronized (ThreadWaitNotify.resource){
            System.out.println("線程["+Thread.currentThread().getName()+"]獲得鎖開始執行");
            try {
                // 釋放鎖,阻塞
                System.out.println("線程["+Thread.currentThread().getName()+"]wait阻塞釋放鎖");
                ThreadWaitNotify.resource.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("線程["+Thread.currentThread().getName()+"]重新獲得鎖");
        }
    }
}

class DoWork3 implements Runnable{
    @Override
    public void run() {
        synchronized (ThreadWaitNotify.resource){
            ThreadWaitNotify.resource.notifyAll();
            System.out.println("線程["+Thread.currentThread().getName()+"]調用notify()");
        }
    }
}

在這裏插入圖片描述
如果把notifyAll()換成notify()呢?
線程0和線程1都在阻塞,而線程2只選擇喚醒一個,那麼應該剩餘一個線程永遠在阻塞了。

class DoWork3 implements Runnable{
    @Override
    public void run() {
        synchronized (ThreadWaitNotify.resource){
            ThreadWaitNotify.resource.notify();
            System.out.println("線程["+Thread.currentThread().getName()+"]調用notify()喚醒一個線程");
        }
    }
}

在這裏插入圖片描述

4.
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章