1. 程式人生 > >Java第十四天學習筆記~多執行緒(執行緒直接通訊---等待喚醒機制、多生產者多消費者問題、JDK1.5新特性、wait和sleep區別)

Java第十四天學習筆記~多執行緒(執行緒直接通訊---等待喚醒機制、多生產者多消費者問題、JDK1.5新特性、wait和sleep區別)

執行緒直接通訊示例

//資源
class Resource
{
	String name;
	String sex;
}
//輸入
class Input implements Runnable
{
	Resource r;
	Input(Resource r)
	{
		this.r=r;
	}
	public void run()
	{
		int x=0;
		while(true)
		{
			if(x==0)
			{
				r.name="mike";
				r.sex="nan";
			}
			else
			{
				r.name="麗麗";
				r.sex="女女女女女女女女女女";
			}
			x=x++%2;
			
		}
	}
}
//輸出

class Output implements Runnable
{
	Resource r;
	Output(Resource r)
	{
		this.r=r;
	}
	public void run()
	{
		while(true)
		{
			System.out.println(r.name+"...."+r.sex);
		}
	}
}

class ResourceDemo
{
	public static void main(String[] args)
	{
		//建立資源
		Resource r=new Resource();
		//建立任務
		Producer in=new Producer(r);
		Consumer out=new Consumer(r);
		//建立執行緒
		Thread t1=new Thread(in);
		Thread t2=new Thread(out);
		//開啟執行緒
		t1.start();
		t2.start();
	}
}

等待喚醒機制

涉及的方法:

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

這些方法是用於操作執行緒狀態的方法

必須要明確到底操作的是哪個鎖上的執行緒

 

為什麼操作執行緒的方法 wait notify notifyAll  定義在了Object類中

因為這些方法是監視器方法,監視器其實就是鎖,鎖可以是任意物件,任意物件呼叫的方式一定定義在Object類中

 

多生產者多消費者問題

/*多生產者多消費者*/


class Resource
{
	private String name;
	private int count=1;
	private boolean flag = false;
	public synchronized void set (String name)
	{
		while(flag)
			try{this.wait();}catch(InterruptedException e){};//t1  t0
		this.name=name+count;//烤鴨1  烤鴨2 烤鴨3
		count++;//2 3 4
		System.out.println(Thread.currentThread().getName()+"...生產者..."+this.name);//生產烤鴨1  生產烤鴨2 生產烤鴨3
		flag=true;
		notify();
	}
	public synchronized void out()//t3
	{
		while(!flag)
			try{this.wait();}catch(InterruptedException e){};//t2 t3
		
		System.out.println(Thread.currentThread().getName()+"...消費者..."+this.name);//消費烤鴨1
		flag=false;
		notify();
	}
}
class Producer implements Runnable
{
	private Resource r;
	Producer(Resource r)
	{
		this.r=r;
	}
	public void run()
	{
		while(true)
		{
			r.set("烤鴨");
		}
	}
}
class Consumer implements Runnable
{
	private Resource r;
	Consumer(Resource r)
	{
		this.r=r;
	}
	public void run()
	{
		while(true)
		{
			r.out();
		}
	}
}
class ProducerConsumerDemo
{
	public static void main(String[] args)
	{
		Resource r=new Resource();
		Producer pro=new Producer(r);
		Consumer con=new Consumer(r);
		
		Thread t1=new Thread(pro);
		Thread t2=new Thread(con);
		t1.start();
		t2.start();
	}
}

while標記,解決了執行緒換區執行權後是否要執行

notifyAll解決了,本方執行緒一定會喚醒對方執行緒

notify:只能喚醒一個執行緒,喚醒本方執行緒無意義而且while判斷標記+notify會導致死鎖

if判斷標記:只有一次,會導致不該執行的執行緒執行,出現數據錯誤情況

JDK1.5新特性

將同步和鎖封裝成了物件,並將操作鎖的隱式方式定義到了該物件中,將隱式動作變成了顯示動作

建立一個鎖物件

lock lock=new Reentrantlook();

void show()
{
    synchronized(obj)
    {
        code.....;           //同步程式碼塊對於鎖的操作是隱式的
    }
}
void show()
{
    lock.lock();    //獲取鎖
    code.....;
    lock.unlock();    //釋放鎖
}

通過已有的鎖獲取該鎖上的監視器物件

Condition con=lock.newCondition( );

通過已有的鎖獲取2組監視器,一組監視生產者一組監視消費者

Condition producer_con=lock.newCondition();

Condition consumer_con=lock.newCondition();

Lock介面:出現替代了同步程式碼塊或同步函式的隱式鎖,操作變成了顯示操作,同時更為靈活,可以一個鎖上加上多組監視器

lock():獲取鎖

unlock():釋放鎖,通常需定義finally程式碼塊中

 

Condition介面:出現代替了object中的wait notify notifyAll 方法,將這些監視器方法單獨進行封裝,變成condition監視器物件,可以任意鎖進行組合。

await();

signal();

signalAll();

 

wait和sleep區別?

//sleep和wait區別
class Demo
{
	void show()
	{
		synchronized(this)
		{
			wait();//t0 t1 t2
		}
	}
	void method()
	{
		synchronized(this)
		{
			//wait();
			notifyAll();
		}//t4
	}
}
class 
{
	public static void main(String[] args)
}

1、wait可以指定時間也可以不指定

  sleep必須指定時間

2、在同步時,對CPU的執行權和鎖的處理不同

wait:釋放執行權,釋放鎖

sleep:釋放執行權,不釋放鎖

執行緒的停止

run方法結束:開啟多執行緒執行,執行程式碼通常是迴圈結構。只要控制住迴圈,就可以讓run方法結束,也就是執行緒結束。

特殊情況:當執行緒處於了凍結狀態。就不會讀取到標記。那麼執行緒就不會結束。

當沒有指定的方式讓凍結的執行緒恢復到執行狀態是,這時需要對凍結進行清除。

強制讓執行緒恢復到執行狀態中來。這樣就可以操作標記讓執行緒結束。Thread類提供該方法 interrupt( );

Thread的其他方法

join():當A執行緒執行到了B執行緒的.join()方法時,A就會等待。等B執行緒都執行完,A才會執行。join可以用來臨時加入執行緒執行。

setDaemon():將該執行緒標記為守護執行緒或使用者執行緒。當正在執行的執行緒都是守護執行緒時,Java 虛擬機器退出。該方法必須在啟動執行緒前呼叫。

setPriority(int newPriority):設定執行緒優先順序,級數為1~10

yield() :暫停當前正在執行的執行緒物件,並執行其他執行緒。