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

 更新时间:2020年07月15日 08:34:32   作者:lkjhgfdsa123  
这篇文章主要介绍了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();
  }
}

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

相关文章

  • 详解Java如何创建Annotation

    详解Java如何创建Annotation

    在本文中,我们将介绍注解的基础知识,包括注解是什么,它们如何在示例中使用,以及如何处理它们。下面和小编一起来学习吧
    2019-05-05
  • java selenium教程环境搭建基于Maven

    java selenium教程环境搭建基于Maven

    本文主要介绍Java selenium 环境的安装,这里介绍了基于Maven的环境搭建,有需要的小伙伴可以参考下
    2016-08-08
  • 使用Java代码进行因数分解和求最小公倍数的示例

    使用Java代码进行因数分解和求最小公倍数的示例

    这篇文章主要介绍了使用Java代码进行因数分解和求最小公倍数的示例,都是基于最基础的算法原理实现,需要的朋友可以参考下
    2015-11-11
  • Java组件commons fileupload实现文件上传功能

    Java组件commons fileupload实现文件上传功能

    这篇文章主要为大家详细介绍了Java组件commons fileupload实现文件上传功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-10-10
  • Spring Security注册过滤器注意事项详解

    Spring Security注册过滤器注意事项详解

    前两天和小伙伴聊了 Spring Security+JWT 实现无状态登录,然后有小伙伴反馈了一个问题,感觉这是一个我们平时写代码容易忽略的问题,所以本文给大家介绍了Spring Security注册过滤器注意事项,需要的朋友可以参考下
    2024-06-06
  • Java代码优化细节

    Java代码优化细节

    这篇文章主要为大家详细介绍了Java代码优化细节,通过不同细节对java代码进行优化,感兴趣的小伙伴们可以参考一下
    2016-08-08
  • spring解决循环依赖的方案示例

    spring解决循环依赖的方案示例

    这篇文章主要介绍spring如何解决循环依赖,文中有相关的代码示例给大家参考,对我们的学习或工作有一定的帮助,感兴趣的同学可以借鉴阅读
    2023-05-05
  • Spring Boot中自定义注解结合AOP实现主备库切换问题

    Spring Boot中自定义注解结合AOP实现主备库切换问题

    这篇文章主要介绍了Spring Boot中自定义注解+AOP实现主备库切换的相关知识,本篇文章的场景是做调度中心和监控中心时的需求,后端使用TDDL实现分表分库,需要的朋友可以参考下
    2019-08-08
  • SpringBoot时区问题解决以及彻底解决时差问题

    SpringBoot时区问题解决以及彻底解决时差问题

    这篇文章主要给大家介绍了关于SpringBoot时区问题解决以及彻底解决时差问题的相关资料,spring boot作为微服务简易架构,拥有其自身的特点,快速搭建架构,简单快捷,需要的朋友可以参考下
    2023-08-08
  • SpringBoot3.x打包Docker容器的实现

    SpringBoot3.x打包Docker容器的实现

    这篇文章主要介绍了SpringBoot3.x打包Docker容器的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-11-11

最新评论