java线程总结(二)——死锁、生产消费者模型

说明:本系列内容部分转载于他人博客,部分自己总结和测试代码。如理解有问题,欢迎博友指正。

本篇主要介绍多线程中两个经典的问题:死锁、生产者和消费者模型

一、死锁

死锁是由于多线程间获取锁时冲突了。比如,有两个线程 A、B,有两个锁 1、2。线程 A 先获取了锁1,在锁1 的代码中需要获取锁 2执行完才释放锁 1,而此时线程 B 获取了锁 2;在锁2 的代码中需要获取锁 1执行完才释放锁 2。此时就发生了死锁

public class TestDeadLock implements Runnable{  
	 
   public int flag = 1;  
    static Object o1 = new Object(), o2 = new Object();  
 
    public static void main(String[] argv){  
        TestDeadLock td1 = new TestDeadLock();  
        TestDeadLock td2 = new TestDeadLock();  
        td1.flag = 1; 
        td2.flag = 0;  
        Thread t1 = new Thread(td1);  
        Thread t2 = new Thread(td2);  
        t1.start();  
        t2.start();  
 
    }  
 
    public void run(){  
 
        System.out.println("flag = "+ flag);  
        if(flag == 1){  
            synchronized (o1){  
                try{  
                    Thread.sleep(500);  
                }catch(Exception e){  
                    e.printStackTrace();  
                }  
 
                synchronized(o2){  
                    System.out.println("1");  
                }  
            }  
        }  
 
        if(flag == 0){  
            synchronized(o2){  
                try{  
                    Thread.sleep(500);  
                }catch(Exception e){  
                    e.printStackTrace();  
                }  
                synchronized(o1){  
                    System.out.println("0");  
                }  
            }  
        }  
    }  
 
}  

解决方案:

  •        让所有的线程按照同样的顺序获得一组锁。这种方法消除了 X 和 Y 的拥有者分别等待对方的资源的问题。
  •   将多个锁组成一组并放到同一个锁下。前面Java线程死锁的例子中,可以创建一个总锁。于是在获得1或2之前都必须获得总锁。

二、生产者消费者模型

这个问题主要就是 wait、notify、notifyAll 的问题,直接上代码

仓库类

import java.util.LinkedList;
import java.util.List;

public class Storage {

	private static int MAX_SIZE;
	private List<Object> list = new LinkedList<>();
	public Storage(int mAX_SIZE) {
		super();
		MAX_SIZE = mAX_SIZE;
	}
	
	public void consume(int num){
		synchronized (list) {
			while(num > list.size()){
				System.out.println("现库存【" + list.size() + "】,消费【" + num + "】。暂时无法消费");
				try {
					list.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			System.out.println("现库存【" + list.size() + "】,消费【" + num + "】。开始消费");
			for(int i=0; i<num; i++){
				list.remove(0);
			}
			list.notifyAll();
		}
	}
	public void produce(int num){
		synchronized (list) {
			while((list.size() + num) > MAX_SIZE){
				System.out.println("现库存空余【" + (MAX_SIZE - list.size()) + "】,生产【" + num + "】。暂时无法生产");
				try {
					list.wait();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}
			System.out.println("现库存空余【" + (MAX_SIZE - list.size()) + "】,生产【" + num + "】。开始生产");
			for(int i=0; i<num; i++){
				list.add(new Object());
			}
			list.notifyAll();
		}
	}
}

生产者类

public class Producer implements Runnable{

	private int num;
	private Storage storage;
	public Producer(Storage storage, int num) {
		super();
		this.num = num;
		this.storage = storage;
	}
	
	public void produce(){
		storage.produce(num);
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		produce();
	}
	
}

消费者类

public class Consumer implements Runnable{

	private int num;
	private Storage storage;
	public Consumer(Storage storage, int num) {
		super();
		this.num = num;
		this.storage = storage;
	}
	
	public void consume(){
		storage.consume(num);
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		consume();
	}
	
}

测试类

public class Test {

	public static void main(String[] args) {
		
		Storage storage = new Storage(100);
		Producer p1 = new Producer(storage, 10);
		Producer p2 = new Producer(storage, 10);
		Producer p3 = new Producer(storage, 10);
		Producer p4 = new Producer(storage, 10);
		Producer p5 = new Producer(storage, 10);
		Producer p6 = new Producer(storage, 10);
		Producer p7 = new Producer(storage, 80);
		
		// 消费者对象
		Consumer c1 = new Consumer(storage, 50);
		Consumer c2 = new Consumer(storage, 20);
		Consumer c3 = new Consumer(storage, 30);
		
		// 线程开始执行
		new Thread(c1).start();
		new Thread(c2).start();
		new Thread(c3).start();

		new Thread(p1).start();
		new Thread(p2).start();
		new Thread(p3).start();
		new Thread(p4).start();
		new Thread(p5).start();
		new Thread(p6).start();
		new Thread(p7).start();
	}
	
}

执行结果:

现库存【0】,消费【50】。暂时无法消费
现库存【0】,消费【30】。暂时无法消费
现库存空余【100】,生产【10】。开始生产
现库存空余【90】,生产【10】。开始生产
现库存空余【80】,生产【10】。开始生产
现库存【30】,消费【20】。开始消费
现库存【10】,消费【30】。暂时无法消费
现库存【10】,消费【50】。暂时无法消费
现库存空余【90】,生产【10】。开始生产
现库存空余【80】,生产【10】。开始生产
现库存空余【70】,生产【10】。开始生产
现库存空余【60】,生产【80】。暂时无法生产
现库存【40】,消费【50】。暂时无法消费
现库存【40】,消费【30】。开始消费
现库存【10】,消费【50】。暂时无法消费
现库存空余【90】,生产【80】。开始生产
现库存【90】,消费【50】。开始消费

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值