当前位置:   article > 正文

Java:双缓冲队列

Java:双缓冲队列

《程序员》:双缓冲队列就是冲着同步/互斥的开销来的。我们知道,在多个线程并发访问同一个资源的时候,需要特别注意线程的同步问题。稍稍不注意,哦活,程序结果不正确了。最经典的就是“银行取钱”的例子,想想,都跟现金挂上钩了,看来这真不容忽视。

今天我们要谈的不是如何去给资源加锁解锁来解决同步问题,今天的重点在于,如何将线程同步的开销降低到我们力所能及的程度。如果你觉得,你可以通过增加硬件资源来弥补程序开销,那么,你将不可能成为一个优秀的程序员。

进入正题,先引入一个例子,两个实体:一个是玩具工厂,它的工作就是不停地生产玩具;另外一个实体就是小孩,它的工作就是不停地从工厂拿玩具。小孩不可能直接到工厂去“拿”玩具吧?呵呵,妈妈是绝对不会放心的。所以,我们有一个“搬运工”,搬运工自然要具备“存放”的功能,不然他怎么将玩具带给小孩呢,是吧。所以,我们先将搬运工定义为一个List,用来存放工厂生产出来的玩具。

玩具类,定义一个玩具实体 >> 

  1. @Data
  2. public class Toy {
  3. private String name;
  4. }

生产玩具的玩具工厂,相当于生产者 >> 

  1. public class Factory extends Thread {
  2. public void run() {
  3. while (true) {
  4. Toy toy = new Toy();
  5. toy.setName("玩具");
  6. synchronized (Tools.lp) {
  7. if (Tools.lp.size() >= 2000) {
  8. try {
  9. Tools.lp.wait();
  10. } catch (Exception e) {
  11. // TODO: handle exception
  12. }
  13. }
  14. Tools.lp.add(t);
  15. // System.out.println("put one");
  16. }
  17. }
  18. }
  19. }

小孩取玩具,相当于消费者 >> 

  1. public class Kid extends Thread {
  2. long time1 = System.currentTimeMillis();
  3. int count = 0;
  4. public void run() {
  5. while (true) {
  6. synchronized (Tools.lt) {
  7. if (Tools.lt.size() != 0){
  8. Tools.lt.remove(0);
  9. count++;
  10. }
  11. }
  12. if (count == 100000) {
  13. System.out.println("time:" + (System.currentTimeMillis() - time1));
  14. System.exit(0);
  15. }
  16. }
  17. }
  18. }

双缓冲队列,里面有两个List >> 

  1. public class DoubleBufferList {
  2. private List<Object> lp;
  3. private List<Object> lt;
  4. private int gap;
  5. public DoubleBufferList(List lp, List lt, int gap) {
  6. this.lp= lp;
  7. this.lt= lt;
  8. this.gap = gap;
  9. }
  10. public void check() {
  11. Runnable runner = new Runnable() {
  12. public void run() {
  13. while (true) {
  14. if (lt.size() == 0) {
  15. synchronized (lt) {
  16. synchronized (lp) {
  17. lt.addAll(lp);
  18. lp.notifyAll();
  19. }
  20. lp.clear();
  21. }
  22. }
  23. }
  24. }
  25. };
  26. Thread thread = new Thread(runner);
  27. thread.start();
  28. }
  29. }

运行的主线程类 >> 

  1. public class BaseTest {
  2. public static void main(String[] args) {
  3. Factory f = new Factory();
  4. f.start();
  5. Kid k = new Kid();
  6. k.start();
  7. new DoubleBufferList(Tools.lp, Tools.lt, 1).check();
  8. }
  9. }

运行结果:比用一个List的生产者消费者模型快很多.大家可以测试下运行速度根据自己的实际情况进行使用

本文内容由网友自发贡献,转载请注明出处:https://www.wpsshop.cn/article/detail/40445
推荐阅读
相关标签
  

闽ICP备14008679号