1. 程式人生 > >Java基礎(三十九)-執行緒相關

Java基礎(三十九)-執行緒相關

生產者與消費者

1:多執行緒開發之中最為著名的案例就是生產者與消費者,該操作的主要流程如下

在這裡插入圖片描述

2:實現程式基本功能和結構

在這裡插入圖片描述在這裡插入圖片描述

public class Test { 
	public static void main(String[] args) throws Exception {
		Message msg = new Message() ;
		new Thread(new Producer(msg)).start(); 	// 啟動生產者執行緒
		new Thread(new Consumer(msg)).start(); 	// 啟動消費者執行緒
	}
}
class Producer implements Runnable {
	private Message msg ; 
	public Producer(Message msg) {
		this.msg = msg ;
	}
	@Override
	public void run() {
		for (int x = 0 ; x < 100 ; x ++) {
			if (x % 2 == 0) {
				this.msg.setTitle("王健");
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				this.msg.setContent("宇宙大帥哥");
			} else {
				this.msg.setTitle("小高");
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				this.msg.setContent("猥瑣第一人,常態保持。");
			}
		}
	}
}
class Consumer implements Runnable {
	private Message msg ;
	public Consumer(Message msg) {
		this.msg = msg ;
	}
	@Override
	public void run() {
		for (int x = 0 ; x < 100 ; x ++) {
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(this.msg.getTitle() + "  -  " + this.msg.getContent());
		}
	}
	
}
class Message {
	private String title ;
	private String content ;
	public void setContent(String content) {
		this.content = content;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getContent() {
		return content;
	}
	public String getTitle() {
		return title;
	}
} 

執行程式碼後發現: 在這裡插入圖片描述

3:解決資料同步

在這裡插入圖片描述

class Message {
	private String title ;
	private String content ;
	public synchronized void set(String title,String content) {
		this.title = title ;
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		this.content = content ;
	}
	public synchronized String get() {
		try {
			Thread.sleep(10);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		return this.title + "  -  " + this.content ;
	}
} 
public class ThreadDemo { 
	public static void main(String[] args) throws Exception {
		Message msg = new Message() ;
		new Thread(new Producer(msg)).start(); 	// 啟動生產者執行緒
		new Thread(new Consumer(msg)).start(); 	// 啟動消費者執行緒
	}
}
class Producer implements Runnable {
	private Message msg ; 
	public Producer(Message msg) {
		this.msg = msg ;
	}
	@Override
	public void run() {
		for (int x = 0 ; x < 100 ; x ++) {
			if (x % 2 == 0) {
				this.msg.set("王健","宇宙大帥哥");
			} else {
				this.msg.set("小高","猥瑣第一人,常態保持。");
			}
		}
	}
}
class Consumer implements Runnable {
	private Message msg ;
	public Consumer(Message msg) {
		this.msg = msg ;
	}
	@Override
	public void run() {
		for (int x = 0 ; x < 100 ; x ++) {
			System.out.println(this.msg.get());
		}
	}
	
}

在進行同步處理的時候肯定需要有一個同步的處理物件,那麼此時肯定要將同步操作交由Message類處理,這個時候發現數據已經可以正常的保持一致了,但是對於重複操作任然存在。

4:執行緒等待與喚醒

在這裡插入圖片描述

在這裡插入圖片描述

如果此時有若干個執行緒的話,notify()表示的是喚醒第一個等待的,而其他執行緒繼續等待,而notify()表示會喚醒多有的執行緒,哪個執行緒的優先順序高就有可能先執行。

對於當前的問題只要的解決應該是通過Message類完成處理。

class Message {
	private String title ;
	private String content ;
	private boolean flag = true ; // 表示生產或消費的形式
	// flag = true:允許生產,但是不允許消費
	// flag = false:允許消費,不允許生產
	public synchronized void set(String title,String content) {
		if (this.flag == false) {	// 無法進行生產,應該等待被消費
			try {
				super.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			} 
		}
		this.title = title ;
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		this.content = content ;
		this.flag = false ; // 已經生產過了
		super.notify(); // 喚醒等待的執行緒
	}
	public synchronized String get() {
		if (this.flag == true) {	// 還未生產,需要等待
			try {
				super.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		try {
			Thread.sleep(10);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		try {
			return this.title + "  -  " + this.content ;
		} finally {	// 不管如何都要執行
			this.flag = true ; // 繼續生產
			super.notify(); // 喚醒等待執行緒
		}
	}
} 
public class Test { 
	public static void main(String[] args) throws Exception {
		Message msg = new Message() ;
		new Thread(new Producer(msg)).start(); 	// 啟動生產者執行緒
		new Thread(new Consumer(msg)).start(); 	// 啟動消費者執行緒
	}
}
class Producer implements Runnable {
	private Message msg ; 
	public Producer(Message msg) {
		this.msg = msg ;
	}
	@Override
	public void run() {
		for (int x = 0 ; x < 100 ; x ++) {
			if (x % 2 == 0) {
				this.msg.set("王健","宇宙大帥哥");
			} else {
				this.msg.set("小高","猥瑣第一人,常態保持。");
			}
		}
	}
}
class Consumer implements Runnable {
	private Message msg ;
	public Consumer(Message msg) {
		this.msg = msg ;
	}
	@Override
	public void run() {
		for (int x = 0 ; x < 100 ; x ++) {
			System.out.println(this.msg.get());
		}
	}
	
}

在這裡插入圖片描述