首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >CyclicBarrier误解

CyclicBarrier误解
EN

Stack Overflow用户
提问于 2014-10-13 10:11:27
回答 1查看 223关注 0票数 0

我尝试使用CyclicBarrier从一个教程中运行示例:当空打印机队列为3时,服务人员应该填充空打印机。但当我运行代码时,打印机中似乎填充了队列中的2、3或4台空打印机:

Printer1是空的 Printer12是空的 Printer14是空的 Printer13是空的 填充Printer1,Printer12,Printer14,Printer13 Printer2是空的 Printer7是空的 填充Printer2,Printer7

那么,这个例子是错误的还是我对CyclicBarrier的理解?我认为队列应该正好有3个元素大小。我应该在代码中添加什么来修复这个问题?提前谢谢。

代码:

代码语言:javascript
复制
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.TimeUnit;

public class PrinterRecharger {
public static void main(String args[]) {
    ServiceMan serviceMan = new ServiceMan(3);

    for (int i = 0; i < 15; i++) {
        new Thread(new Printer(serviceMan, "Printer" + (i + 1))).start();
    }
}
}

class ServiceMan {

private CyclicBarrier queue;
private List<String> inQueue;

public ServiceMan(int hardWorking) {
    inQueue = new ArrayList<String>();
    queue = new CyclicBarrier(hardWorking, new Runnable() {
        @Override
        public void run() {
            System.out.println("Filling " + inQueue);
            inQueue.clear();
        }
    });
}

public void recharge(String name) {
    try {
        inQueue.add(name);
        queue.await();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (BrokenBarrierException e) {
        e.printStackTrace();
    }
}

}

class Printer implements Runnable {

private String name;
private Random rand;
private ServiceMan serviceMan;

public Printer(ServiceMan serviceMan, String name) {
    this.name = name;
    this.serviceMan = serviceMan;
    this.rand = new Random();
}

public void run() {
    try {
        while (true) {
            TimeUnit.SECONDS.sleep(rand.nextInt(10));
            System.out.println(name + " is empty");
            serviceMan.recharge(name);
        }
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

}
EN

回答 1

Stack Overflow用户

发布于 2014-10-13 10:23:36

您的代码在几个方面是线程不安全的,我可以立即看到,而且可能还有一些我忽略了的代码。您有数据竞赛以及其他类型的竞赛条件。

  • ArrayList不是一个线程安全类,但是您可以在没有同步的多个线程中使用它.将列表包装到一个Collections.synchronizedList()中,以看到一些改进。
  • recharge()CyclicBarrier的操作之间缺乏任何互斥关系。线程可以向队列中添加一个项,结果被该操作清除掉。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/26337508

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档