java多线程(同步与死锁问题,生产者与消费者问题)

首先我们来看同步与死锁问题:

所谓死锁,就是A拥有banana,B拥有apple。

A对B说:你把apple给我,我就把banana给你。

B对A说:你把banana给我,我就把apple给你。

但是A和B都在等待对方的答复,那么这样最终的结果就是A得不到apple,B也得不到banana。这种死循环就是死锁。

于是我们可以模拟上面的描述,写出以下代码:

类A代表A这个人,

public class A {
	public void say(){
		System.out.println("A said to B: if you give me the apple, I will give you the banana.");
	}
	public void get(){
		System.out.println("A get the apple.");
	}
}

类B代表B这个人,

public class B {
	public void say(){
		System.out.println("B said to A: if you give me the banana, I will give you the apple.");
	}
	public void get(){
		System.out.println("B get the banana.");
	}
}

类ThreadDeadLock代表死锁类,

public class ThreadDeadLock implements Runnable{
	private static A a=new A();
	private static B b=new B();
	public boolean flag=false;
	public void run(){
		if(flag){
			synchronized(a){
				a.say();
				try{
					Thread.sleep(500);
				}catch(InterruptedException e){
					e.printStackTrace();
				}
				synchronized(b){
					a.get();
				}
			}
		}else{
			synchronized(b){
				b.say();
				try{
					Thread.sleep(500);
				}catch(InterruptedException e){
					e.printStackTrace();
				}
				synchronized(a){
					b.get();
				}
			}
		}
	}
}

下面是主类:

public class Main{
	public static void main(String[] args){
		ThreadDeadLock t1=new ThreadDeadLock();
		ThreadDeadLock t2=new ThreadDeadLock();
		t1.flag=true;
		t2.flag=false;
		Thread thA=new Thread(t1);
		Thread thB=new Thread(t2);
		thA.start();
		thB.start();
	}
}

程序运行结果:

A said to B: if you give me the apple, I will give you the banana.

B said to A: if you give me the banana, I will give you the apple.

从以上的程序运行,我们可以发现,两个线程都在等待对方的执行完成,这样,程序也就无法继续执行,从而造成了死锁运行现象。

下面我们来看生产者与消费者问题:

所谓生产者与消费者问题,很简单,过程就是生产者不断生产产品,消费者不断取走产品。

Producer生产product,Consumer消费product。

于是,我们先定义product类:

public class Product {
	private String name="product";
	private boolean flag=false;
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public synchronized void set(String name){
		if(!flag){
			try{
				super.wait();
			}catch(InterruptedException e){
				e.printStackTrace();
			}
		}
		this.setName(name);
		try{
			Thread.sleep(300);
		}catch(InterruptedException e){
			e.printStackTrace();
		}
		flag=false;
		super.notify();
	}
	public synchronized void get(){
		if(flag){
			try{
				super.wait();
			}catch(InterruptedException e){
				e.printStackTrace();
			}
		}
		try{
			Thread.sleep(300);
		}catch(InterruptedException e){
			e.printStackTrace();
		}
		System.out.println(this.getName());
		flag=true;
		super.notify();
	}
}

这里加入了等待与唤醒,并增加一个标志位flag,flag为true时,表示可以生产,但不能取走,此时如果线程执行到了消费者线程,则应该等待,如果flag为false,则表示可以取走,但是不能生产,如果生产者线程运行,则应该等待。

Producer类:

public class Producer implements Runnable{
	private Product product=null;
	public Producer(Product product){
		this.product=product;
	}
	public void run(){
		for(int i=0;i<50;++i){
			this.product.set("product");
		}
	}
}

Consumer类:

public class Consumer implements Runnable{
	private Product product=null;
	public Consumer(Product product){
		this.product=product;
	}
	public void run(){
		for(int i=0;i<50;++i){
			try{
				Thread.sleep(100);
			}catch(InterruptedException e){
				e.printStackTrace();
			}
			this.product.get();
		}
	}
}

然后是主类:

public class Main{
	public static void main(String[] args){
		Product product=new Product();
		Producer pro=new Producer(product);
		Consumer con=new Consumer(product);
		new Thread(pro).start();
		new Thread(con).start();
	}
}

于是我们知道,生产者每生产一个产品,消费者就取走一个产品,消费者每取走一个产品,就要等待生产者生产。

时间: 2024-12-20 22:59:12

java多线程(同步与死锁问题,生产者与消费者问题)的相关文章

Java线程同步与死锁、生产者消费者模式以及任务调度等

一.Thread类基本信息方法 package Threadinfo; public class MyThread implements Runnable{ private boolean flag = true; private int num = 0; @Override public void run() { while(flag) { System.out.println(Thread.currentThread().getName()+"-->"+num++); } }

Java多线程虚假唤醒问题(生产者和消费者关系)

何为虚假唤醒: 当一个条件满足时,很多线程都被唤醒了,但是只有其中部分是有用的唤醒,其它的唤醒都是无用功:比如买货:如果商品本来没有货物,突然进了一件商品,这是所有的线程都被唤醒了,但是只能一个人买,所以其他人都是假唤醒,获取不到对象的锁: 避免虚假唤醒: 避免虚假唤醒的示例:这里使用了 Lambda 表达式 package com.jia.pc; public class A { public static void main(String[] args) { Data data = new

Java多线程-同步:synchronized 和线程通信:生产者消费者模式

大家伙周末愉快,小乐又来给大家献上技术大餐.上次是说到了Java多线程的创建和状态|乐字节,接下来,我们再来接着说Java多线程-同步:synchronized 和线程通信:生产者消费者模式. 一.同步:synchronized 多个线程同时访问一个对象,可能造成非线程安全,数据可能错误,所谓同步:就是控制多个线程同时访就是控制多线程操作同一个对象时,注意是同一个对象,数据的准确性, 确保数据安全,但是加入同步后因为需要等待,所以效率相对低下. 如:一个苹果,自己一个人去咬怎么都不会出问题,但是

Java入门——同步与死锁

Java入门——同步与死锁 同步 解决资源共享的同步操作,可以使用同步代码块和同步方法两种方法完成. 1 package Sep19; 2 3 class MyThread implements Runnable{ 4 private int ticket=5; 5 public void run(){//覆写run方法 6 for(int i=0;i<100;i++){ 7 if (ticket>0){ 8 try{ 9 Thread.sleep(3000); 10 }catch(Inter

Java多线程中的死锁问题[转]

//申明:本文转载自http://www.cnblogs.com/digdeep/p/4448148.html <Java多线程中的死锁问题> Java程序基本都要涉及到多线程,而在多线程环境中不可避免的要遇到线程死锁的问题.Java不像数据库那么能够检测到死锁,然后进行处理,Java中的死锁问题,只能通过程序员自己写代码时避免引入死锁的可能性来解决. 1. Java中导致死锁的原因 Java中死锁最简单的情况是,一个线程T1持有锁L1并且申请获得锁L2,而另一个线程T2持有锁L2并且申请获得

java基础知识回顾之java Thread类学习(七)--java多线程安全问题(死锁)

死锁:是两个或者两个以上的线程被无限的阻塞,线程之间互相等待所需资源. 线程死锁产生的条件: 当两个线程相互调用Join()方法. 当两个线程使用嵌套的同步代码块的时候,一个线程占用了另一个线程的锁,互相等待阻塞,就有可能产生死锁. 下面看代码: 代码1:死锁的案例 package com.lp.ecjtu.Thread; /* 死锁:常见情景之一:同步的嵌套. */ class Ticket implements Runnable { private int num = 100; Object

java基础知识回顾之java Thread类学习(六)--java多线程同步函数用的锁

1.验证同步函数使用的锁----普通方法使用的锁 思路:创建两个线程,同时操作同一个资源,还是用卖票的例子来验证.创建好两个线程t1,t2,t1线程走同步代码块操作tickets,t2,线程走同步函数封装的代码操作tickets,同步代码块中的锁我们可以指定.假设我们事先不知道同步函数用的是什么锁:如果在同步代码块中指定的某个锁(测试)和同步函数用的锁相同,就不会出现线程安全问题,如果锁不相同,就会发生线程安全问题. 看下面的代码:t1线程用的同步锁是obj,t2线程在操作同步函数的资源,假设不

转:关于JAVA多线程同步

转:http://lanvis.blog.163.com/blog/static/26982162009798422547/ 因为需要,最近关注了一下JAVA多线程同步问题.JAVA多线程同步主要依赖于若干方法和关键字.将心得记录如下: 1  wait方法:        该方法属于Object的方法,wait方法的作用是使得当前调用wait方法所在部分(代码块)的线程停止执行,并释放当前获得的调用wait所在的代码块的锁,并在其他线程调用notify或者notifyAll方法时恢复到竞争锁状态

java多线程之 ---- 线程死锁

java多线程之线程死锁 产生死锁的主要原因: 因为系统资源不足. 进程运行推进的顺序不合适. 资源分配不当等. 如果系统资源充足,进程的资源请求都能够得到满足,死锁出现的可能性就很低,否则就会因争夺有限的资源而陷入死锁.其次, 进程运行推进顺序与速度不同,也可能产生死锁. 产生死锁的四个必要条件:  互斥条件:一个资源每次只能被一个进程使用. 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放. 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺. 循环等待条件:若干进

多线程-线程间通信-多生产者多消费者示例

1.多线程-线程间通信-多生产者多消费者问题 多生产者和多消费者.等待唤醒机制. 产生了两个问题: 1.出现了多次连续生产,未消费,或者一个商品被消费多次. 解决:必须要--------每一个被唤醒的线程判断一次标记,所以将if判断改为while判断. 2.出现了死锁. 本方唤醒了本方,导致了所有的线程都等待了. 解决方式就是:唤醒所有等待的线程.这样既唤醒了本方也唤醒对方. 虽然解决了多生产消费的问题,但是有些低效. 解决方法一: 唤醒所有等待的线程 class Resource{     p