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();
 }
}

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

本文永久更新链接地址

相关内容