JAVA線程sleep()和wait()詳解及實(shí)例
JAVA線程sleep()和wait()詳解及實(shí)例
sleep
1.sleep是Thread的一個靜態(tài)(static)方法。使得Runnable實(shí)現(xiàn)的線程也可以使用sleep方法。而且避免了線程之前相互調(diào)用sleep()方法,引發(fā)死鎖。
2.sleep()執(zhí)行時需要賦予一個沉睡時間。在沉睡期間(阻塞線程期間),CPU會放棄這個線程,執(zhí)行其他任務(wù)。當(dāng)沉睡時間到了之后,該線程會自動蘇醒,不過此時線程不會立刻被執(zhí)行,而是要等CPU分配資源,和其他線程進(jìn)行競爭。
3.此外如果這個線程之前獲取了一個機(jī)鎖,在沉睡期間,這個機(jī)鎖不會釋放。其他等待這個機(jī)鎖的程序,必須等待這個線程醒來,且執(zhí)行完后才能運(yùn)行。
sleep相關(guān)代碼
public class ThreadTest2 {
public static void main(String[] args){
System.out.println("begin our test");
ThreadSleep sleep = new ThreadSleep();
try {
Thread thread1 = new Thread(sleep,"路人甲");
Thread thread2 = new Thread(sleep,"路人乙");
thread1.start();
thread2.start();
}catch(Exception e){
e.printStackTrace();
}
System.out.println("test is over");
}
}
class ThreadSleep implements Runnable{
int count = 0;
@Override
public void run(){
System.out.println(Thread.currentThread().getName() + " say : hello sleep !!");
count();
}
public void count(){
while(count < 20) {
System.out.println(Thread.currentThread().getName() + " say : count is " + count);
try {
count++;
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
輸出日志
begin our test test is over 路人甲 say : hello sleep !! 路人甲 say : count is 0 路人乙 say : hello sleep !! 路人乙 say : count is 1 路人甲 say : count is 2 路人乙 say : count is 2 路人甲 say : count is 4 路人乙 say : count is 4 路人甲 say : count is 6 路人乙 say : count is 7 路人乙 say : count is 8 路人甲 say : count is 8 路人甲 say : count is 10 路人乙 say : count is 10 路人乙 say : count is 12 路人甲 say : count is 12 路人乙 say : count is 14 路人甲 say : count is 14 路人甲 say : count is 16 路人乙 say : count is 16 路人甲 say : count is 18 路人乙 say : count is 18
通過日志可以發(fā)現(xiàn)線程甲和線程乙基本是交替執(zhí)行,但是并不規(guī)律,且出現(xiàn)了并發(fā)問題。
該情況是由于代碼中設(shè)置了睡眠時間為100毫秒,由于count遞增執(zhí)行速度很快,所以線程差不多是同時睡眠,然后同時蘇醒并導(dǎo)致了并發(fā)的出現(xiàn)。
接下來要添加synchronize塊,檢查sleep時機(jī)鎖是否釋放
public class ThreadTest2 {
public static void main(String[] args){
System.out.println("begin our test");
ThreadSleep sleep = new ThreadSleep();
try {
Thread thread1 = new Thread(sleep,"路人甲");
Thread thread2 = new Thread(sleep,"路人乙");
thread1.start();
thread2.start();
}catch(Exception e){
e.printStackTrace();
}
System.out.println("test is over");
}
}
class ThreadSleep implements Runnable{
int count = 0;
@Override
public void run(){
System.out.println(Thread.currentThread().getName() + " say : hello sleep !!");
count();
}
public void count(){
while(count < 20) {
synchronized (this) {
System.out.println(Thread.currentThread().getName() + " say : count is " + count);
try {
count++;
Thread.sleep(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
輸出日志
begin our test 路人甲 say : hello sleep !! 路人甲 say : count is 0 test is over 路人乙 say : hello sleep !! 路人甲 say : count is 1 路人甲 say : count is 2 路人甲 say : count is 3 路人甲 say : count is 4 路人甲 say : count is 5 路人甲 say : count is 6 路人甲 say : count is 7 路人甲 say : count is 8 路人甲 say : count is 9 路人甲 say : count is 10 路人甲 say : count is 11 路人甲 say : count is 12 路人甲 say : count is 13 路人甲 say : count is 14 路人甲 say : count is 15 路人甲 say : count is 16 路人甲 say : count is 17 路人甲 say : count is 18 路人甲 say : count is 19 路人乙 say : count is 20
通過日志可以看出,基本是線程甲在執(zhí)行,這是因?yàn)閟leep時,機(jī)鎖一直在線程甲上,所以線程乙只能一直等待直到線程甲釋放鎖。
wait
1.wait()是Object類的一個方法。當(dāng)調(diào)用wait()方法時,該線程會進(jìn)入和該對象相關(guān)的等待池中,并釋放它所擁有的機(jī)鎖。
2.執(zhí)行wait()后,必須使用notify()方法或notifyAll()方法或設(shè)置等待時間(wait(long time))喚醒在等待線程池中的線程。
3.wait()必須放在synchronized block中,否則會在運(yùn)行時報“java.lang.IllegalMonitorStateException”異常
wait相關(guān)代碼
public class ThreadTest2 {
public static void main(String[] args) {
System.out.println("begin our test");
ThreadSleep sleep = new ThreadSleep();
try {
Thread thread1 = new Thread(sleep, "路人甲");
Thread thread2 = new Thread(sleep, "路人乙");
thread1.start();
thread2.start();
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("test is over");
}
}
class ThreadSleep implements Runnable {
int count = 0;
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " say : hello sleep !!");
count();
}
public void count() {
while (count < 20) {
synchronized (this) {
System.out.println(Thread.currentThread().getName() + " say : count is " + count);
try {
count++;
this.wait(100);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
輸出日志
begin our test 路人甲 say : hello sleep !! 路人甲 say : count is 0 test is over 路人乙 say : hello sleep !! 路人乙 say : count is 1 路人甲 say : count is 2 路人乙 say : count is 3 路人甲 say : count is 4 路人乙 say : count is 5 路人甲 say : count is 6 路人乙 say : count is 7 路人甲 say : count is 8 路人乙 say : count is 9 路人甲 say : count is 10 路人乙 say : count is 11 路人甲 say : count is 12 路人乙 say : count is 13 路人乙 say : count is 14 路人甲 say : count is 15 路人乙 say : count is 16 路人甲 say : count is 17 路人乙 say : count is 18 路人甲 say : count is 19
通過日志可以發(fā)現(xiàn)在wait的情況下,機(jī)鎖會被釋放。
感謝閱讀,希望能幫助到大家,謝謝大家對本站的支持!
相關(guān)文章
java實(shí)現(xiàn)追加內(nèi)容到文件末尾的常用方法分析
這篇文章主要介紹了java實(shí)現(xiàn)追加內(nèi)容到文件末尾的常用方法,結(jié)合具體實(shí)例分析了java文件流及寫入指針等相關(guān)操作技巧,需要的朋友可以參考下2017-10-10
詳解java創(chuàng)建一個女朋友類(對象啥的new一個就是)==建造者模式,一鍵重寫
這篇文章主要介紹了java建造者模式一鍵重寫,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-04-04
Java Swing實(shí)現(xiàn)餐廳點(diǎn)餐系統(tǒng)源碼(收藏版)
這篇文章主要介紹了Java Swing實(shí)現(xiàn)餐廳點(diǎn)餐系統(tǒng)源碼,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02
Mybatis?TypeHandler接口及繼承關(guān)系示例解析
這篇文章主要為大家介紹了Mybatis?TypeHandler接口及繼承關(guān)系示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-02-02

