Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 这是在多线程中计数的正确方法吗?_Java_Multithreading - Fatal编程技术网

Java 这是在多线程中计数的正确方法吗?

Java 这是在多线程中计数的正确方法吗?,java,multithreading,Java,Multithreading,我想在5个线程完成后从WorkerThread类获取所有计数。计数器是否按预期的方式工作?谢谢在WorkerThread构造函数中,似乎每个计数器成为每个线程的一个变量,而不是在5个线程之间共享 public class Test { public static void main(String[] args) { ExecutorService executor = Executors.newFixedThreadPool(5); Counter co

我想在5个线程完成后从WorkerThread类获取所有计数。计数器是否按预期的方式工作?谢谢在WorkerThread构造函数中,似乎每个计数器成为每个线程的一个变量,而不是在5个线程之间共享

public class Test {

    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(5);
        Counter counter = new Counter();
        for (int i = 0; i < 10; i++) {
            Runnable worker = new WorkerThread(String.valueOf(i), counter);
            executor.execute(worker);
          }
        executor.shutdown();
        System.out.println("Total Count: " + counter.value());
        while (!executor.isTerminated()) {
        }
        System.out.println("Finished all threads");
    }

}

class Counter{
    private AtomicInteger count;

    public Counter(){
        count = new AtomicInteger();
    }

    public int increment(){
        return count.incrementAndGet();
    }

    public int value(){
        return count.get();
    }
}

class WorkerThread implements Runnable {

    private String command;
    private Counter c;

    public WorkerThread(String s, Counter c){
        this.command=s;
        this.c = c;
    }

    @Override
    public void run() {
        for(int i=0; i<6; i++){         
            c.increment();
        }
        processCommand();       
    }

    private void processCommand() {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Override
    public String toString(){
        return this.command;
    }
}
公共类测试{
公共静态void main(字符串[]args){
ExecutorService executor=Executors.newFixedThreadPool(5);
计数器=新计数器();
对于(int i=0;i<10;i++){
Runnable worker=new WorkerThread(String.valueOf(i),计数器);
执行人,执行人(工人);
}
executor.shutdown();
System.out.println(“总计数:+counter.value());
而(!executor.isTerminated()){
}
System.out.println(“完成所有线程”);
}
}
班级计数器{
私有原子整数计数;
公众柜位(){
count=新的原子整数();
}
公共整数增量(){
返回count.incrementAndGet();
}
公共int值(){
返回count.get();
}
}
类WorkerThread实现Runnable{
私有字符串命令;
私人柜台c;
公共WorkerThread(字符串s,计数器c){
this.command=s;
这个.c=c;
}
@凌驾
公开募捐{

对于(int i=0;i同步对我来说似乎是正确的。如果计数是您唯一的任务,您可以跳过计数器类,直接使用AtomicInteger来消除复杂性。(如果您想要实现更复杂的任务,需要适当的同步共享状态对象,请保留它)

不要称你的工人类为“线程”。它不是一个线程,而是一个由线程执行的任务

最后但并非最不重要的一点是,您的关机代码有问题。请注意,关机不会阻塞,而是立即返回。因此,您对计数器的评估太早了

以下代码修复了所有这些问题:

public class Test {
    public static void main(String[] args) {
        ExecutorService executor = Executors.newFixedThreadPool(5);
        AtomicInteger counter = new AtomicInteger();

        for (int i = 0; i < 10; i++) {
            executor.execute(new Worker(counter));
        }

        executor.shutdown();
        if (!executor.awaitTermination(60, TimeUnit.SECONDS)) {
            // executor does not shut down.
            // try executor.shutdownNow() etc.
        }

        System.out.println("Total Count: " + counter.get());
    }
}

class Worker implements Runnable {
    private final AtomicInteger counter;

    public Worker(AtomicInteger counter) {
        this.counter = counter;
    }

    public void run() {
        // do something
        counter.incrementAndGet();
        // do something else
    }
}
公共类测试{
公共静态void main(字符串[]args){
ExecutorService executor=Executors.newFixedThreadPool(5);
AtomicInteger计数器=新的AtomicInteger();
对于(int i=0;i<10;i++){
执行人。执行人(新工人(柜台));
}
executor.shutdown();
如果(!执行器等待终止(60,时间单位秒)){
//执行器不会关闭。
//尝试executor.shutdownNow()等。
}
System.out.println(“总计数:+counter.get());
}
}
类工作者实现可运行的{
专用最终原子整数计数器;
公共工作者(原子整数计数器){
this.counter=计数器;
}
公开募捐{
//做点什么
counter.incrementAndGet();
//做点别的
}
}

有关如何正确关闭
ExecutorService
的更多信息,请参阅“使用示例”一节。

我不理解这个问题。问题是什么?您不应该
e.printStackTrace()
一个
InterruptionException
。至少应该
Thread.currentThread().interrupt()
。此外,为了便于阅读,您可以使用
时间单位。秒。睡眠(5L);
。您可能想浏览一下本教程;它将让您了解
这个.c=c
实际上在做什么。的javadoc表示它不会等待线程终止。我多次运行该程序,结果似乎并不总是正确的。有时是30,有时是24。在切换时应该始终是30g直接使用
AtomicInteger
可以简化此特定示例中的代码,我绝对不建议将其作为一般方法。使用
计数器
类可以添加其他功能,例如值更改时的回调和进度通知,以及等待计数器达到特定值的能力值(以及根据需求切换到其他实现的能力,例如
信号量
倒计时闩锁
等).a
AtomicInteger
本身并没有太多功能。我同意。但在那个特定的示例中,计数器类使代码更加复杂,并分散了对同步主要问题的注意力。不过,我会更新我的答案。