前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >多线程使用wait和notify做生产者消费者模型导致线程全部假死

多线程使用wait和notify做生产者消费者模型导致线程全部假死

作者头像
用户1215919
发布2018-02-27 10:29:22
6910
发布2018-02-27 10:29:22
举报

分析假死的原因:

首先我们每次只生产一个数据,然后消费者进行消费,

public class Value {
	public static String value = "";//这个值作为生产消费的容器
}

生产者端代码:

private String lock;

	public Producer (String lock) {
		super();
		this.lock = lock;

	}

	public void setValue() {
		try {
			synchronized (lock) {
				while (!"".equals(Value.value)) {
					System.out.println("生產者:"+Thread.currentThread().getName()+"等待");
					lock.wait();
				}
				System.out.println("生產者:"+Thread.currentThread().getName()+"开始工作了");
				String value = "Producer";
				System.out.println("set value :"+value);
				Value.value = value;
				lock.notify();
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}

消费者端

private String lock;

	public Consumer(String lock) {
		this.lock = lock;

	}

	public void getValue() {
		try {
			synchronized (lock) {
				if ("".equals(Value.value)) {
					System.out.println("消费者:"+Thread.currentThread().getName()+"等待");
					lock.wait();
				}
				System.out.println("消费者:"+Thread.currentThread().getName()+"开始消费了");
				System.out.println("get value :"+Value.value );
				Value.value = "";
				lock.notify();
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

	}
public class MyThread1 extends Thread {
	private Producer p;

	public MyThread1(Producer  p) {
		this.p = p;
	}
	
	@Override
	public void run() {
		while(true){
			p.setValue();//此线程不停的生产
		}
		
	}
package com.demo.thread;

public class MyThread2 extends Thread{
	private Consumer c;
	public MyThread2(Consumer c) {
		this.c = c;
	}
	
	@Override
	public void run() {
		while (true) {
			c.getValue();//此线程不听的消费
			
		}
	}
}

测试:

String lock = new String("lock");
		Producer p = new Producer (lock);
		Consumer c = new Consumer (lock);
		MyThread1[] t1 = new MyThread1[2];
		
		MyThread2 [] t2 = new MyThread2[2];
		
		for(int i = 0 ;i<2;i++){
			t1[i] = new MyThread1(p);
			t1[i].setName("生产者:"+(i+1));
			t2[i] = new MyThread2(c);
			t2[i].setName("消费者:"+(i+1));
			t1[i].start();
			t2[i].start();
			
		}
		
		Thread.sleep(3000);
		Thread[] tArr = new Thread [Thread.currentThread().getThreadGroup().activeCount()];
		Thread.currentThread().getThreadGroup().enumerate(tArr);
		for(int i = 0 ;i<tArr.length;i++){
			System.out.println(tArr[i].getName()+"\t"+tArr[i].getState());
		}

截取控制台代码部分代码: 分析:因为notify每次只唤醒一个线程,因此并不确定他唤醒的是哪一个线程,所以消费1唤醒的是消费者2,此时刚好没有数据被生产,消费者2也进入等待,并唤醒生产者2,生产者2生产完数据之后进入wait同时唤醒线程,此时唤醒的是生产者1 ,因为数据不为空,因此两生产者都进入等待状态,此时四个线程全部wait,即假死状态,结果如控制台所示. 解决方式:这里每次执行完毕之后应该唤醒所有线程即可.

生產者:生产者:2开始工作了
set value :Producer
消费者:消费者:1开始消费了
get value :Producer
消费者:消费者:1等待
生產者:生产者:2开始工作了
set value :Producer
生產者:生产者:2等待
生產者:生产者:1等待
消费者:消费者:2开始消费了
get value :Producer
消费者:消费者:2等待
生產者:生产者:2开始工作了
set value :Producer
生產者:生产者:2等待
生產者:生产者:1等待
消费者:消费者:1开始消费了
get value :Producer
消费者:消费者:1等待//消费者1等待,唤醒消费者2
消费者:消费者:2开始消费了
get value :
消费者:消费者:2等待//消费者2唤醒生产者2
生產者:生产者:2开始工作了
set value :Producer
生產者:生产者:2等待//从这里开始,生产者2唤醒1,两者最后都进入wait.
生產者:生产者:1等待
main	RUNNABLE
生产者:1	WAITING
消费者:1	WAITING
生产者:2	WAITING
消费者:2	WAITING
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档