首页 > 编程语言 > Java多种方式实现生产者消费者模式
2020
10-08

Java多种方式实现生产者消费者模式

实现需求:两个线程交替打印1,0,打印10轮

java多线程口诀:

  • 高内聚,低耦合
  • 线程操作资源类
  • 判断干活通知
  • 防止虚假唤醒

方式一:使用synchronized和Object的wait和notifyAll方法

wait:使当前线程阻塞

notify,notifyAll唤醒当前线程

/**
 * 两个线程交替打印1,0 打印10轮
 *
 * @author Administrator
 * @version 1.0 2020年7月12日
 * @see ProdConsumerDemo1
 * @since 1.0
 *
 */
class ShareData1 {
 
  public int number = 0;
 
  public synchronized void increment() throws Exception {
    while (number != 0) {
      this.wait();
    }
    number++;
    System.out.println(Thread.currentThread().getName() + " " + number);
    this.notifyAll();
  }
 
  public synchronized void decrement() throws InterruptedException {
    while (number != 1) {
      this.wait();
    }
    number--;
    System.out.println(Thread.currentThread().getName() + " " + number);
    this.notifyAll();
  }
}
 
public class ProdConsumerDemo1 {
 
  public static void main(String[] args) {
    ShareData1 shareData = new ShareData1();
    new Thread(() -> {
      for (int i = 0; i < 10; i++) {
        try {
          shareData.increment();
        } catch (Exception e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    }, "A").start();
    new Thread(() -> {
      for (int i = 0; i < 10; i++) {
        try {
          shareData.decrement();
        } catch (Exception e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    }, "B").start();
  }
}

输出结果

A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0

方式二:使用jdk1.8的Lock和Condition

class ShareData2 {
 
  private int number = 0;
 
  private Lock lock = new ReentrantLock();
 
  private Condition condition = lock.newCondition();
 
  public void increment() throws Exception {
    lock.lock();
    try {
      while (number != 0) {
        condition.await();
      }
      number++;
      System.out.println(Thread.currentThread().getName() + " " + number);
      condition.signalAll();
    } finally {
      lock.unlock();
    }
  }
 
  public void decrement() throws InterruptedException {
    lock.lock();
    try {
      while (number != 1) {
        condition.await();
      }
      number--;
      System.out.println(Thread.currentThread().getName() + " " + number);
      condition.signalAll();
    } finally {
      // TODO: handle finally clause
      lock.unlock();
    }
  }
}
 
public class ProdConsumerDemo2 {
 
  public static void main(String[] args) {
    ShareData2 shareData = new ShareData2();
    new Thread(() -> {
      for (int i = 0; i < 10; i++) {
        try {
          shareData.increment();
        } catch (Exception e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    }, "A").start();
    new Thread(() -> {
      for (int i = 0; i < 10; i++) {
        try {
          shareData.decrement();
        } catch (Exception e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    }, "B").start();
  }
}

输出结果

A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0
A 1
B 0

主要是熟悉Lock和Condition的使用

Lock和Condition相比于synchronized,能够精确唤醒

需求:三个线程A,B,C顺序打印,A打印5次,B打印10次,C打印15次,10轮

class ShareData3 {
 
  private int number = 1;
 
  private Lock lock = new ReentrantLock();
 
  private Condition c1 = lock.newCondition();
 
  private Condition c2 = lock.newCondition();
 
  private Condition c3 = lock.newCondition();
 
  public void print5() throws Exception {
    lock.lock();
    try {
      while (number != 1) {
        c1.await();
      }
      number = 2;
      for (int i = 0; i < 5; i++) {
        System.out.println(Thread.currentThread().getName() + " " + i);
      }
      c2.signalAll();
    } finally {
      // TODO: handle finally clause
      lock.unlock();
    }
  }
 
  public void print10() throws InterruptedException {
    lock.lock();
    try {
      while (number != 2) {
        c2.await();
      }
      number=3;
      for (int i = 0; i < 10; i++) {
        System.out.println(Thread.currentThread().getName() + " " + i);
      }
      c3.signalAll();
    } finally {
      // TODO: handle finally clause
      lock.unlock();
    }
  }
 
  public void print15() throws InterruptedException {
    lock.lock();
    try {
      while (number != 3) {
        c3.await();
      }
      number = 1;
      for (int i = 0; i < 15; i++) {
        System.out.println(Thread.currentThread().getName() + " " + i);
      }
      c1.signalAll();
    } finally {
      // TODO: handle finally clause
      lock.unlock();
    }
  }
}
 
public class ProdConsumerDemo3 {
 
  public static void main(String[] args) {
    ShareData3 shareData3 = new ShareData3();
    new Thread(() -> {
      try {
        for (int i = 0; i < 10; i++) {
          shareData3.print5();
        }
      } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }, "A").start();
    new Thread(() -> {
      try {
        for (int i = 0; i < 10; i++) {
          shareData3.print10();
        }
      } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }, "B").start();
    new Thread(() -> {
      try {
        for (int i = 0; i < 10; i++) {
          shareData3.print15();
        }
      } catch (Exception e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
      }
    }, "C").start();
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持自学编程网。

编程技巧