Java學習——併發編程之多線程之間通信

三.多線程之間通信

1.爲什麼有線程之間的通信?

(1)線程在運行時,cpu是隨機調度的,往往我們會使用多個線程來完成同一個任務(類似多人協作),並且我們希望多線程完成任務是有規律的,那麼在完成任務的過程中,線程之間必然要有一些交流,這樣才能使用同一份數據進行操作。

(2)多線程使用同一份數據來完成任務,必然就會造成資源的爭奪,所以引入線程的通信可以解決這樣一個問題。

2.什麼是線程之間的通信

多線程之間的通信就是多個線程共同操作同一個共享變量,一個線程在佔用共享變量時,通知其他線程進行等待(wait()方法),使用完畢後,將其他線程喚醒(notify()和notifyall()方法)。這就是線程的等待喚醒機制wait()notify()。線程之間通信最典型的例子就是生產者與消費者問題。

3.wait、notify 方法

(1)因爲涉及到對象鎖,他們必須都放在synchronized中來使用. Wait()、Notify()一定要在synchronized裏面進行使用。

(2)Wait()必須暫定當前正在執行的線程,並釋放資源鎖,讓其他線程可以有機會運行

(3)notify/notifyall: 喚醒因鎖池中的線程,使之運行

注意:一定要在線程同步中使用,並且是同一個鎖的資源

4.演示生產者和消費者

package thread_demo3;
/**
 * 多線程之間通訊,生產者消費者
 * @author johson
 *  1.因爲涉及到對象鎖,他們必須都放在synchronized中來使用. Wait、Notify一定要在synchronized裏面進行使用。
 *	2.Wait必須暫定當前正在執行的線程,並釋放資源鎖,讓其他線程可以有機會運行
 *	3. notify/notifyall: 喚醒線程,使之運行
 *
 */

//生產的對象
class Person{
	String name;
	
	String sex;
	
	//flag==false時,只寫不度
	//flag==true時,只讀不寫
	boolean flag = false;
	
}

//生產者進程
class writeThread extends Thread{
	
	public Person person;
	
	public writeThread(Person person) {
		this.person = person;
	}
	
	@Override
	public void run() {

		int count = 0;
		
		while(true){
			synchronized (person) {
				//當flag==true的時候,消費者去讀取person
				if(person.flag){
					try {
						person.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					try {
						Thread.sleep(1000);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				//當flag==false時,生產person,然後通知消費者去讀取
				else {
					if(count == 0){
						person.name = "小紅";
						person.sex = "女";
					}
					
					else {
						person.name = "小軍";
						person.sex = "男";
					}
					
					System.out.println("生產者生產"+person.name+","+person.sex);
					
					count = (count+1)%2;
					
					person.flag = true;
					
					person.notify();
				}
			}

		}

	}
}

//消費者進程
class readThread extends Thread{
	
	public Person person;
	
	public readThread(Person person) {
		this.person = person;
	}
	
	@Override
	public void run() {
		while (true) {
			synchronized (person) {
				//flag==false時,等待生產者生產person
				if(!person.flag){
					try {
						person.wait();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				//flag==true時,消費者讀取person,然後將flag變成false,通知生產者去生產person
				else {
					System.out.println("消費者消費"+person.name+","+person.sex);
					person.flag = false;
					person.notify();
				}
				
			}
			
		}
	}
}

public class test1 {
	
	public static void main(String[] args) {
		//新建一個person對象
		Person person = new Person();
		//生產者
		writeThread write = new writeThread(person);
		//消費者
		readThread read = new readThread(person);
		
		write.start();
		
		read.start();
	}
	

}

運行結果如下:

5.waitsleep區別

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

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

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

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章