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

作者:lkjhgfdsa123 时间:2023-12-13 05:56:16 

实现需求:两个线程交替打印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();
 }
}

来源:https://www.cnblogs.com/lt123/p/13290098.html

标签:java,生产者,消费者
0
投稿

猜你喜欢

  • android 设置全屏的两种方法

    2023-06-30 00:06:11
  • 关于Scanner对象的输入结束标记问题

    2022-02-20 08:02:11
  • 详解Java中的ThreadLocal

    2022-08-19 17:48:43
  • Android 中启动自己另一个程序的activity如何实现

    2022-05-17 05:24:56
  • Java基础之Spring5的核心之一IOC容器

    2022-06-04 07:44:14
  • C# List集合中获取重复值及集合运算详解

    2022-06-13 17:15:45
  • Spring MVC Mybatis多数据源的使用实例解析

    2022-02-13 20:37:19
  • Android编程之json解析实例详解

    2023-06-19 15:32:51
  • Android使用ViewPager加载图片和轮播视频

    2023-10-26 08:20:04
  • 使用Gradle做Java代码质量检查的方法示例

    2021-08-10 00:45:06
  • C#远程发送和接收数据流生成图片的方法

    2021-08-31 00:30:10
  • 客户端Socket与服务端ServerSocket串联实现网络通信

    2023-08-11 00:01:17
  • Java中初始化List集合的八种方式汇总

    2021-09-20 22:31:54
  • Java开发中synchronized的定义及用法详解

    2021-11-11 07:01:20
  • Spring Cloud Ribbon客户端详细介绍

    2023-11-27 21:36:22
  • Android10 分区存储的适配规则

    2022-11-25 12:22:53
  • c#中Invoke与BeginInvoke的用法及说明

    2023-06-10 12:39:49
  • AndroidStudio4.0 New Class的坑(小结)

    2022-07-29 15:06:48
  • Java四种权限修饰符知识点详解

    2023-11-11 06:12:59
  • C#利用Task实现任务超时多任务一起执行的方法

    2023-07-04 20:03:38
  • asp之家 软件编程 m.aspxhome.com