玩轉java多線程(wait和notifyAll的正確使用姿勢)


轉載請標明博客的地址

本人博客和github賬號,如果對你有幫助請在本人github項目AioSocket上點個star,激勵作者對社區貢獻

敲代碼誰都會,關鍵敲出性能好而又簡潔易懂易維護的代碼並不是每個程序員都能做到,關鍵是要找好姿勢,這樣才能避免很多坑。

對了,今天聊的是wait和notifyAll的正確使用姿勢。(繼上一篇玩轉Java多線程(乒乓球比賽)https://www.cnblogs.com/haibiscuit/p/11094348.html)

貼出代碼前,首先先講一下程序的邏輯規則:

        1.  6個線程,3個線程執行++操作,3個線程執行--操作,保證線程的同步和並發要求

        2.  每個線程循環n次操作,默認是20次

        3.  執行++操作時數據不能超出20,執行--操作時數據不能低於0

 

貼出代碼:

package Thread;

import java.util.concurrent.CountDownLatch;

/**
* wait方法和Notify方法寫在實體類對象中
* wait代表退出當前線程對某實體對象的操作,釋放鎖暫時退出當前線程的操作,由其他線程調用該對象的notify方法來釋放前一個線程,繼續對該對象進行操作
*/
public class AwaitTest {
public static void main(String[] args)
{
CountDownLatch countDownLatch = new CountDownLatch(6);
NumberHolder numberHolder = new NumberHolder();

Thread t1 = new IncreaseThread(numberHolder,countDownLatch);
Thread t2 = new DecreaseThread(numberHolder,countDownLatch);

Thread t3 = new IncreaseThread(numberHolder,countDownLatch);
Thread t4 = new DecreaseThread(numberHolder,countDownLatch);

Thread t5 = new IncreaseThread(numberHolder,countDownLatch);
Thread t6 = new DecreaseThread(numberHolder,countDownLatch);


t1.start();
t2.start();

t3.start();
t4.start();

t5.start();
t6.start();


try {
countDownLatch.await();
System.out.println("主線程執行結束!");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}

}

}


class NumberHolder
{ //**********非常重要
private int number; //這里number執行increase的次數和執行decrease的次數要相同,
//否則可能造成線程一直處於wait狀態,除非將下面的while改成if
private int i; //標記執行的次數,測試CountDownLatch類

public synchronized void increase()
{
while (20 == number) //當前的number為10的時候,對象當前的線程進入等待的狀態
{
try
{
this.wait(500);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}

// 能執行到這里說明已經被喚醒
// 並且number為0
number++;
System.out.println("執行次數"+(++i));
System.out.println(number);

// 通知在等待的線程
this.notifyAll();
}

public synchronized void decrease()
{
while (0 == number) //當前對象的number等於0時,進入等待的狀態
{
try
{
this.wait(500);
}
catch (InterruptedException e)
{
e.printStackTrace();
}

}

// 能執行到這里說明已經被喚醒
// 並且number不為0
number--;
System.out.println("執行次數"+(++i));
System.out.println(number);
this.notifyAll();
}

}
//線程類:用於控制實體類下面的數據相加
class IncreaseThread extends Thread
{
private NumberHolder numberHolder;
private CountDownLatch countDownLatch;

public IncreaseThread(NumberHolder numberHolder,CountDownLatch countDownLatch)
{
this.numberHolder = numberHolder;
this.countDownLatch = countDownLatch;
}

@Override
public void run()
{
for (int i = 0; i < 20; ++i)
{
// 進行一定的延時
try
{
Thread.sleep((long) Math.random() * 1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}

// 進行增加操作

numberHolder.increase();
}
countDownLatch.countDown();
}

}
//線程類,完成對實體類的操作
class DecreaseThread extends Thread
{
private NumberHolder numberHolder;
private CountDownLatch countDownLatch;

public DecreaseThread(NumberHolder numberHolder,CountDownLatch countDownLatch)
{
this.numberHolder = numberHolder;
this.countDownLatch = countDownLatch;
}

@Override
public void run()
{
for (int i = 0; i < 20; ++i)
{
// 進行一定的延時
try
{
Thread.sleep((long) Math.random() * 1000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}

// 進行減少操作
numberHolder.decrease();
}
countDownLatch.countDown();
}

}

 

總結:

       1.wait方法要在synchronized方法體內使用,另外如果有限制條件需要結合while使用   (不建議結合if使用)

       2.notifyAll()方法需要在synchronized方法內使用    (不建議使用notify方法)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM