溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Java怎么使用wait或notify實(shí)現(xiàn)線程間通信

發(fā)布時間:2022-12-13 09:12:15 來源:億速云 閱讀:100 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹“Java怎么使用wait或notify實(shí)現(xiàn)線程間通信”,在日常操作中,相信很多人在Java怎么使用wait或notify實(shí)現(xiàn)線程間通信問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Java怎么使用wait或notify實(shí)現(xiàn)線程間通信”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!

1. 當(dāng) interrupt() 方法遇到 wait() 方法

當(dāng)線程調(diào)用鎖對象的wait() 方法使線程呈等待狀態(tài)時,調(diào)用線程對象的 interrupt() 方法會出現(xiàn) InterruptedException 異常。

public class ThreadC7 {
    @Test
    public void test1() {
        try {
            Object obj = new Object();
            ThreadC7A threadC7A = new ThreadC7A(obj);
            threadC7A.start();
            Thread.sleep(2000);
            threadC7A.interrupt();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
class ServiceC7 {
    public void testMethod(Object obj) {
        try {
            synchronized (obj) {
                System.out.println("begin wait");
                obj.wait();
                System.out.println("begin end");
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("出現(xiàn)異常了,wait狀態(tài)的線程被interrupt了!");
        }
    }
}
class ThreadC7A extends Thread {
    private Object obj;
    public ThreadC7A(Object obj) {
        this.obj = obj;
    }
    @Override
    public void run() {
        ServiceC7 serviceC7 = new ServiceC7();
        serviceC7.testMethod(obj);
    }
}

執(zhí)行結(jié)果:

Java怎么使用wait或notify實(shí)現(xiàn)線程間通信

2. notify() 只通知一個線程

調(diào)用方法notify()一次只隨機(jī)通知一個線程進(jìn)行喚醒。

public class ThreadC8 {
    @Test
    public void test() {
        Object obj = new Object();
        ThreadC8A threadC8A = new ThreadC8A(obj);
        threadC8A.setName("threadC8A");
        threadC8A.start();
        ThreadC8B threadC8B = new ThreadC8B(obj);
        threadC8B.setName("threadC8B");
        threadC8B.start();
        ThreadC8C threadC8C = new ThreadC8C(obj);
        threadC8C.setName("threadC8C");
        threadC8C.start();
        try {
            Thread.sleep(1000);
        } catch (Exception e) {
            e.printStackTrace();
        }
        synchronized (obj) {
            obj.notify();
        }
        while (Thread.activeCount() > 1) {
        }
    }
}
class ServiceC8 {
    public void service(Object obj) {
        try {
            synchronized (obj) {
                String threadName = Thread.currentThread().getName();
                System.out.println("begin wait,Thread Name:[" + threadName + "]");
                obj.wait();
                System.out.println("end wait,Thread Name:[" + threadName + "]");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
class ThreadC8A extends Thread {
    private Object obj;
    public ThreadC8A(Object obj) {
        this.obj = obj;
    }
    @Override
    public void run() {
        ServiceC8 serviceC8 = new ServiceC8();
        serviceC8.service(obj);
    }
}
class ThreadC8B extends Thread {
    private Object obj;
    public ThreadC8B(Object obj) {
        this.obj = obj;
    }
    @Override
    public void run() {
        ServiceC8 serviceC8 = new ServiceC8();
        serviceC8.service(obj);
    }
}
class ThreadC8C extends Thread {
    private Object obj;
    public ThreadC8C(Object obj) {
        this.obj = obj;
    }
    @Override
    public void run() {
        ServiceC8 serviceC8 = new ServiceC8();
        serviceC8.service(obj);
    }
}

執(zhí)行結(jié)果:

Java怎么使用wait或notify實(shí)現(xiàn)線程間通信

程序運(yùn)行的效果如圖所示,可以看出方法notify()僅隨機(jī)喚醒一個線程。

當(dāng)多次調(diào)用notify()方法時,會隨機(jī)將等待wait狀態(tài)的線程進(jìn)行喚醒。更改代碼如下:

Java怎么使用wait或notify實(shí)現(xiàn)線程間通信

再次運(yùn)行,程序運(yùn)行效果如圖所示,可以看出所有的線程全部被喚醒。

Java怎么使用wait或notify實(shí)現(xiàn)線程間通信

多次調(diào)用notify()方法可喚醒全部WAITING中的線程。

3. notifyAll() 喚醒所有線程

前面的示例中通過多次調(diào)用 notify() 方法來實(shí)現(xiàn)喚醒3個線程,但并不能保證系統(tǒng)中僅有3個線程,也就是若notify()方法的調(diào)用次數(shù)小于線程對象的數(shù)量,會出現(xiàn)有部分線程對象無法被喚醒的情況。為了喚醒全部線程,可以使用notifyAll()方法。

更改代碼如下:

Java怎么使用wait或notify實(shí)現(xiàn)線程間通信

再次運(yùn)行,程序運(yùn)行效果如圖所示,可以看出所有的線程全部被喚醒。

Java怎么使用wait或notify實(shí)現(xiàn)線程間通信

4. 方法 wait(long)的使用

帶一個參數(shù)的wait(long) 方法的功能是等待某一時間內(nèi)是否有現(xiàn)成對鎖進(jìn)行喚醒,如果超過這個時間則自動喚醒。

public class ThreadC9 {
    @Test
    public void test() {
        Object obj = new Object();
        ThreadC9A threadC9A = new ThreadC9A(obj);
        threadC9A.start();
        while (Thread.activeCount() > 1) {
        }
    }
}
class ThreadC9A extends Thread {
    private Object obj;
    public ThreadC9A(Object obj) {
        this.obj = obj;
    }
    @Override
    public void run() {
        try {
            synchronized (obj) {
                long startTime = System.currentTimeMillis();
                System.out.println("begin wait,time:[" + startTime + "]");
                obj.wait(5000);
                long endTime = System.currentTimeMillis();
                System.out.println("end wait,time:[" + endTime + "] takes " + (endTime - startTime) + " ms");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

執(zhí)行結(jié)果:

Java怎么使用wait或notify實(shí)現(xiàn)線程間通信

通過執(zhí)行結(jié)果可以看出,在經(jīng)過5000ms后,線程被喚醒。

到此,關(guān)于“Java怎么使用wait或notify實(shí)現(xiàn)線程間通信”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注億速云網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI