(十六)java併發程式設計--執行緒的死鎖解決方案(生產者和消費者幾種實現方式)
阿新 • • 發佈:2018-12-24
上一篇中,主要了解了什麼時候死鎖,並且提出死鎖的一個解決方案,多個鎖要按照一定的順序來。
本片主要是利用生產者消費者模式解決執行緒的死鎖。
多執行緒生產者和消費者一個典型的多執行緒程式。一個生產者生產提供消費的東西,但是生產速度和消費速度是不同的。這就需要讓生產者和消費者執行不同的執行緒,通過共享區域或者佇列來協調他們。如下圖所示:
程式碼如下:
package deadlock.comsumer_product_solution;
import java.util.ArrayList;
import java.util.List;
/**
* Created by fang on 2017/12/8.
* 生產者消費者經典模式.
*/
public class ClassicProducerConsumer {
public static class Producer implements Runnable{
private List<Integer> queue;
private int next = 0;
public Producer (List<Integer> queue){
this.queue = queue;//共享資源新增資料.
}
public void run() {
while (true){
//生產資源.
synchronized (queue){//鎖住list中的物件.
queue.add(next);//生產時鎖住這個陣列
// System.out.println("product number" + next + "thread name: " + Thread.currentThread().getName());
queue.notifyAll();//喚醒其他執行緒.
}
next++;
}
}
}
public static class Consumer implements Runnable{
private List<Integer> queue;
public Consumer(List<Integer> queue){
this.queue = queue;
}
public void run() {
while (true){
if(queue.size()>0){
Integer number = queue.remove(queue.size() -1);
System.out.println("cunsoumer number..."+number + "thread name: " + Thread.currentThread().getName());
}else {
try {
queue.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public static void main(String args[]) throws Exception{
List<Integer> queue = new ArrayList<Integer>();
Thread producter1 = new Thread(new Producer(queue),"product1 thread");
Thread producter2 = new Thread(new Producer(queue),"product2 therad");
Thread consumer1 = new Thread(new Consumer(queue),"consumer1 therad");
Thread consumer2 = new Thread(new Consumer(queue),"consumer2 therad");
producter1.start();
producter2.start();
consumer1.start();
consumer2.start();
}
}
自從java1.5之後有很多容易的方式去實現生產者和消費者方案,最好的方式就是使用a blocking queue。
package deadlock.comsumer_product_solution;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.SynchronousQueue;
/**
* Created by fang on 2017/12/8.
* using block queue .
*/
public class producerConsumerWithBlockingQueue {
public static class Producer implements Runnable{
private BlockingQueue<Integer>queue;
private int next = 0;
public Producer(BlockingQueue<Integer> queue){
this.queue = queue;
}
public void run() {
while (true){
try {
queue.put(next);
System.out.println(next + "product");
} catch (InterruptedException e) {
e.printStackTrace();
}
next++;
}
}
}
public static class Consumer implements Runnable{
private BlockingQueue<Integer> queue;
private Consumer(BlockingQueue<Integer> queue){
this.queue = queue;
}
public void run() {
while (true){
synchronized (queue){
Integer next ;
try {
next = queue.take();
System.out.println(next+"consumer");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
public static void main(String[] args) {
BlockingQueue<Integer> queue = new LinkedBlockingDeque<Integer>(1);
Thread producer1 = new Thread(new Producer(queue));
Thread producer2 = new Thread(new Producer(queue));
Thread consumer1 = new Thread(new Consumer(queue));
Thread consumer2 = new Thread(new Consumer(queue));
producer1.start();
producer2.start();
consumer1.start();
consumer2.start(); }
}
如果有一個生產者和一個消費者,我們可以使用count down latch,程式碼如下:
package deadlock.comsumer_product_solution;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
/**
* Created by fang on 2017/12/8.
* countdownlatch
*/
public class ProducerConsumerWithCountDownLatch {
public static class Producer implements Runnable {
private List<Integer> queue;
private CountDownLatch latch;
private int next = 0;
public Producer(List<Integer> queue,CountDownLatch latch) {
this.queue = queue;
this.latch=latch;
}
public void run() {
while (true) {
synchronized (queue) {
queue.add(next);
System.out.println(next + "producer");
latch.countDown();
}
next++;
}
}
}
public static class Consumer implements Runnable {
private List<Integer> queue;
private CountDownLatch latch;
public Consumer(List<Integer> queue,CountDownLatch latch) {
this.queue = queue;
this.latch=latch;
}
public void run() {
while (true) {
Integer number=null;
synchronized (queue) {
if (queue.size() > 0) {
number = queue.remove(queue.size()-1);
System.out.println(number+"consumer");
}
}
if(number==null) {
try {
latch.await();
} catch (InterruptedException e) {
}
}
}
}
}
public static void main(String args[]) throws Exception {
List<Integer> queue = new ArrayList<Integer>();
CountDownLatch latch=new CountDownLatch(1);
Thread producer1 = new Thread(new Producer(queue,latch));
Thread consumer1 = new Thread(new Consumer(queue,latch));
producer1.start();
consumer1.start();
}
}
如果一個生產者和一個消費者,我們還可以使用Exchanger,程式碼如下:
package deadlock.comsumer_product_solution;
import java.util.concurrent.Exchanger;
/**
* Created by fang on 2017/12/8.
* 使用exchanger.
*/
public class ProducerConsumerWithExchanger {
public static class Producer implements Runnable {
private Exchanger<Integer> exchanger;
private int next = 0;
public Producer(Exchanger<Integer> exchanger) {
this.exchanger=exchanger;
}
public void run() {
while (true) {
try {
exchanger.exchange(next);
System.out.println(next +"producer");
} catch (InterruptedException e) {
}
next++;
}
}
}
public static class Consumer implements Runnable {
private Exchanger<Integer> exchanger;
public Consumer(Exchanger<Integer> exchanger) {
this.exchanger=exchanger;
}
public void run() {
while (true) {
try {
System.out.println(exchanger.exchange(0) + "consumer");
} catch (InterruptedException e) {
}
}
}
}
public static void main(String args[]) throws Exception {
Exchanger<Integer> exchanger=new Exchanger<Integer>();
Thread producer1 = new Thread(new Producer(exchanger));
Thread consumer1 = new Thread(new Consumer(exchanger));
producer1.start();
consumer1.start();
}
}
以上幾種方式就是實現生產者和消費者解決方案,同時也解決了死鎖問題。