Java线程中wait、await、sleep、yield、join用法总结
生活随笔
收集整理的這篇文章主要介紹了
Java线程中wait、await、sleep、yield、join用法总结
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
文章目錄
- 一、wait()、notify()、notifyAll()用法
- 二、await()、signal()、signalAll()用法
- 三 、yield()、join()用法
- 四、wait()、await()、sleep()、yield、join對(duì)比
一、wait()、notify()、notifyAll()用法
- obj.wait()/obj.wait(long timeout)是Object中的方法,當(dāng)線程調(diào)用wait()方法,當(dāng)前線程釋放對(duì)象鎖,進(jìn)入等待隊(duì)列。
- obj.notify()/obj.nogifyAll()是Object中的方法,喚醒在此對(duì)象上wait()的單個(gè)或者所有線程。
測(cè)試代碼:
public class ThreadWaitNotify {public static void main(String[] args) throws InterruptedException {//創(chuàng)建一個(gè)線程池ExecutorService executorService = Executors.newCachedThreadPool();//創(chuàng)建DemoTest對(duì)象DemoTest demoTest = new DemoTest();//用線程池創(chuàng)建線程異步執(zhí)行waitTest方法executorService.submit(() -> demoTest.waitTest());//用線程池創(chuàng)建線程異步執(zhí)行notifyTest方法executorService.submit(() -> demoTest.notifyTest());}//測(cè)試wait和notify測(cè)試demostatic class DemoTest {//喚醒線程public synchronized void notifyTest() {System.out.println("方法notifyTest開始執(zhí)行了");notify();System.out.println("方法notifyTest執(zhí)行結(jié)束了");}//執(zhí)行wait操作將線程掛起,注意必須結(jié)合synchronized使用public synchronized void waitTest() {System.out.println("方法waitTest開始執(zhí)行了");try {wait();} catch (InterruptedException e) {e.printStackTrace();}System.out.println("方法waitTest執(zhí)行結(jié)束了");}} }打印日志:
方法waitTest開始執(zhí)行了 方法notifyTest開始執(zhí)行了 方法notifyTest執(zhí)行結(jié)束了 方法waitTest執(zhí)行結(jié)束了從日志中我們可以看出waitTest方法阻塞直到被notifyTest喚醒
二、await()、signal()、signalAll()用法
java.util.concurrent類庫中提供的Condition類來實(shí)現(xiàn)線程之間的協(xié)調(diào)。
- condition.await()/condition.await(long time, TimeUnit unit):通過condition調(diào)用,當(dāng)前線程釋放對(duì)象鎖。
- condition.signal()/condition.signalAll():通過signal或者signalAll方法喚醒a(bǔ)wait掛起的線程。
測(cè)試代碼:
public class ThreadAwaitSignal {public static void main(String[] args) {//創(chuàng)建一個(gè)線程池ExecutorService executorService = Executors.newCachedThreadPool();//創(chuàng)建DemoTest對(duì)象DemoTest demoTest = new DemoTest();//用線程池創(chuàng)建線程異步執(zhí)行awaitTest方法executorService.submit(() -> demoTest.awaitTest());//用線程池創(chuàng)建線程異步執(zhí)行signalTest方法executorService.submit(() -> demoTest.signalTest());}/*** 使用java.util.conncurrent類中提供了Condition類來實(shí)現(xiàn)線程之間的協(xié)調(diào)* 可以在Condition上調(diào)用await()方法使線程掛起* 其他線程調(diào)用signal()或者signalAll()來喚醒線程*/static class DemoTest {//定義一個(gè)Lock對(duì)象用來獲取Condition對(duì)象private Lock lock = new ReentrantLock();private Condition condition = lock.newCondition();//喚醒線程public void signalTest() {lock.lock();try {System.out.println("方法signalTest開始執(zhí)行了");condition.signalAll();System.out.println("方法signalTest執(zhí)行結(jié)束了");} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}//結(jié)合lock鎖實(shí)現(xiàn)Condition的awaitpublic void awaitTest() {lock.lock();try {System.out.println("方法awaitTest開始執(zhí)行了");condition.await();System.out.println("方法awaitTest執(zhí)行結(jié)束了");} catch (InterruptedException e) {e.printStackTrace();} finally {lock.unlock();}}} }打印日志:
方法awaitTest開始執(zhí)行了 方法signalTest開始執(zhí)行了 方法signalTest執(zhí)行結(jié)束了 方法awaitTest執(zhí)行結(jié)束了從日志中國可以看出我們得到了和wait同樣的效果。
三 、yield()、join()用法
- Thread.yield():一定是當(dāng)前線程調(diào)用此方法,當(dāng)前線程放棄獲取CPU的時(shí)間片,由運(yùn)行態(tài)轉(zhuǎn)變?yōu)榫途w態(tài),讓操作系統(tǒng)中再次選擇線程執(zhí)行。作用:讓相同優(yōu)先級(jí)的線程輪流執(zhí)行,但并不能保證輪流執(zhí)行,根據(jù)解釋我們了解到,轉(zhuǎn)成就緒態(tài)的的線程還有可能再次選中執(zhí)行。Thread.yield()方法不會(huì)導(dǎo)致阻塞。
- t.join()/t.join(long millis):當(dāng)前線程調(diào)用t2.join()方法,當(dāng)前線程阻塞但是不會(huì)釋放對(duì)象鎖,直到t2線程執(zhí)行完畢或者millis時(shí)間到,則當(dāng)前的線程恢復(fù)就緒狀態(tài)。作用:讓優(yōu)先級(jí)比較高的線程優(yōu)先執(zhí)行。
yield測(cè)試代碼:
//yield放棄CPU時(shí)間片public static void yieldTest(){//定義一個(gè)線程Thread thread = new Thread(() -> {System.out.println(Thread.currentThread().getName() + ": 測(cè)試線程開始執(zhí)行。。。");try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + ": 測(cè)試線程執(zhí)行結(jié)束了。");});thread.start();System.out.println(Thread.currentThread().getName() + ": 執(zhí)行yield方法");Thread.yield();System.out.println(Thread.currentThread().getName() + ": 主線程開始執(zhí)行");}打印結(jié)果:
main: 執(zhí)行yield方法 main: 主線程開始執(zhí)行 Thread-0: 測(cè)試線程開始執(zhí)行。。。 Thread-0: 測(cè)試線程執(zhí)行結(jié)束了。可以看出雖然主線程調(diào)用了yield,但是仍然又開始執(zhí)行了,因此但并不能保證輪流執(zhí)行。
join測(cè)試代碼:
//join搶占CPU時(shí)間片public static void joinTest() throws InterruptedException {//定義一個(gè)線程Thread thread = new Thread(() -> {System.out.println(Thread.currentThread().getName() + ": 測(cè)試線程開始執(zhí)行。。。");try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + ": 測(cè)試線程執(zhí)行結(jié)束了。");});thread.start();System.out.println(thread.getName() + ": 執(zhí)行join方法");thread.join();System.out.println(Thread.currentThread().getName() + ": 主線程開始執(zhí)行");}打印日志:
Thread-0: 執(zhí)行join方法 Thread-0: 測(cè)試線程開始執(zhí)行。。。 Thread-0: 測(cè)試線程執(zhí)行結(jié)束了。 main: 主線程開始執(zhí)行從日志中我們可以看出主線程在線程執(zhí)行完成后才開始執(zhí)行。
四、wait()、await()、sleep()、yield、join對(duì)比
通過表格對(duì)比(join的情況下,t1指代當(dāng)前線程,t2代表其他線程)
| 是否釋放持有鎖 | 釋放 | 釋放 | 不釋放 | 不釋放 | t1不釋放 |
| 誰的方法 | Object | Condition | Thread | Thread | 線程對(duì)象 |
| 喚醒方法 | nogify/nogifyAll | signal/signalAll | 指定時(shí)間后 | 自動(dòng)喚醒 | t2執(zhí)行完自動(dòng)喚醒 |
| 何時(shí)就緒 | 喚醒后就緒 | 喚醒后就緒 | 指定時(shí)間后就緒 | 立刻進(jìn)入就緒 | t2完成后進(jìn)入就緒 |
| 執(zhí)行環(huán)境 | 同步代碼塊 | 同步代碼快 | 任意位置 | 任意位置 | 任意位置 |
總結(jié)
以上是生活随笔為你收集整理的Java线程中wait、await、sleep、yield、join用法总结的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: JAVA线程的生命周期以及5种状态转换
- 下一篇: Java中synchronized和Lo