線程間通信(等待,喚醒)&Java中sleep()和wait()比較


1.什么是線程間通信?

  多個線程在處理同一資源,但是任務卻不同

生活中栗子:有一堆煤,有2輛車往里面送煤,有2輛車往外拉煤,這個煤就是同一資源,送煤和拉煤就是任務不同。

 

 2.等待/喚醒機制。

  涉及的方法:

  (1)wait(): 讓線程處於凍結狀態,被wait的線程會被存儲到線程池(容器)中
  (2)notify():喚醒線程池中一個線程(任意).
  (3)notifyAll():喚醒線程池中的所有線程。

  這些方法都必須定義在同步中
  因為這些方法是用於操作線程狀態的方法。
  必須要明確到底操作的是哪個鎖上的線程。

  什么是線程池?

  顧名思義就是事先創建若干個可執行的線程放入一個池(容器)中,需要的時候從池中獲取線程而不用自行創建,使用完畢后不需要銷毀放入池中,從而減少創建和銷毀對象的開銷。


  為什么操作線程的方法wait notify notifyAll定義在了Object類中

  因為這些方法是監視器的方法。監視器其實就是鎖,就是栗子中的r
  鎖可以是任意的對象,任意的對象調用的方式一定定義在Object類中。

栗子:(誰拿鎖誰執行) 

class Resource
{
	private String name;
	private String sex;
	private boolean flag = false;

	public synchronized void set(String name,String sex)
	{
		if(flag)//為真的時候,就直接進入wait,這樣該線程就釋放了執行權了。為假就執行下面的語句
			try{this.wait();}catch(InterruptedException e){}
		this.name = name;
		this.sex = sex;
		flag = true;
		this.notify();//喚醒輸出線程,輸出線程具備了執行資格。搶來了CPU執行權
	}

	public synchronized void out()
	{
		if(!flag)
			try{this.wait();}catch(InterruptedException e){}
		System.out.println(name+"...+...."+sex);
		flag = false;
		notify();//喚醒輸入線程
	}
}

//輸入
class Input implements Runnable
{
	Resource r ;
//	Object obj = new Object();
	Input(Resource r)
	{
		this.r = r;
	}
	public void run()
	{
		int x = 0;
		while(true)
		{
			if(x==0)
			{
				r.set("mike","nan");
			}
			else
			{
				r.set("麗麗","女女女女女女");
			}
			x = (x+1)%2;
		}
	}
}
//輸出
class Output implements Runnable
{

	Resource r;
//	Object obj = new Object();
	Output(Resource r)
	{
		this.r = r;
	}

	public void run()
	{
		while(true)
		{
			r.out();
		}
	}
}

class  ResourceDemo3
{
	public static void main(String[] args) 
	{
		//創建資源。
		Resource r = new Resource();
		//創建任務。
		Input in = new Input(r);
		Output out = new Output(r);
		//創建線程,執行路徑。
		Thread t1 = new Thread(in);
		Thread t2 = new Thread(out);
		//開啟線程
		t1.start();
		t2.start();
	}
}

3.sleep()和wait()比較

 (1)對於sleep()方法,我們首先要知道該方法是屬於Thread類中的。而wait()方法,則是屬於Object類中的。

 (2)sleep()方法導致了程序暫停執行指定的時間,讓出cpu該其他線程,但是他的監控狀態依然保持着,當指定的時間到了又會自動恢復運行狀態。

 (3)在調用sleep()方法的過程中,線程不會釋放對象鎖。

  而當調用wait()方法的時候,線程會放棄對象鎖,進入等待此對象的等待鎖定池,只有針對此對象調用notify()方法后本線程才進入對象鎖定池准備獲取對象鎖進入運行狀態。

 (4)wait可以指定時間也可以不指定時間,sleep必須指定時間

 (5)在同步中時,對cpu的執行權和鎖的處理不同。
  wait:釋放執行權,釋放鎖
  sleep:釋放執行權,不釋放鎖

栗子:

  關於sleep和wait,以下描述錯誤的是D

   A.sleep是線程類的方法,wait是object的方法

   B.sleep不釋放對象鎖,wait放棄對象鎖

   C.sleep暫停線程,但監控狀態依然保持,結束后會自動恢復

   D.wait進入等待鎖定池,只有針對此對象發出notify方法獲得對象鎖進入運行狀態

原因:是D中,准備獲取對象鎖進入運行狀態,而不是立即進入

4.線程狀態

 


免責聲明!

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



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