【问题标题】:Not getting expected output while using Countdownlatch and Executor in java在 java 中使用 Countdownlatch 和 Executor 时没有得到预期的输出
【发布时间】:2013-02-27 23:27:24
【问题描述】:

我是 Java 多线程 的新手。尝试学习Java线程中的countdownlatch和executor,实现如下代码-

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ExecutorBasicFramework {


    class MyThread extends Thread{

        int iCount ; String name;
        CountDownLatch latch;

        public MyThread(int iCount, String name, CountDownLatch latch) {
            super();
            this.iCount = iCount;
            this.name = name;
            this.latch = latch;         
        }

        @Override
        public void run() {
            for(int i=0;i<10;i++){
                System.out.println(name+" Printing .... "+ ++iCount+" L "+latch.getCount());
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }               
            }
            latch.countDown();

        }

    }

    public ExecutorBasicFramework() {
        createThread();
    }


    private void createThread() {
        ExecutorService exec = Executors.newFixedThreadPool(10);
        CountDownLatch latch = new CountDownLatch(10);
        for(int i=0;i<10;i++){          
            MyThread thread = new MyThread(i*10, ""+i,latch);
            exec.execute(thread);

            try {
                latch.await();
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }

        exec.shutdownNow();     

    }

    public static void main(String[] args) {
        new ExecutorBasicFramework();
    }

}

输出如下 -

0 Printing .... 1 L 10
0 Printing .... 2 L 10
0 Printing .... 3 L 10
0 Printing .... 4 L 10
0 Printing .... 5 L 10
0 Printing .... 6 L 10
0 Printing .... 7 L 10
0 Printing .... 8 L 10
0 Printing .... 9 L 10
0 Printing .... 10 L 10

然后流程就像继续等待。 我的预期输出与上面类似,但在打印 0 之后,它应该打印 1 到 9 的类似输出,然后程序应该停止。

我认为倒计时锁正在等待和等待,它不会增加执行程序的下一个计数器。所以我无法获得预期的输出。 我期待像 -

这样的输出
0 Printing .... 1 L 10
0 Printing .... 2 L 10
0 Printing .... 3 L 10
0 Printing .... 4 L 10
0 Printing .... 5 L 10
0 Printing .... 6 L 10
0 Printing .... 7 L 10
0 Printing .... 8 L 10
0 Printing .... 9 L 10
0 Printing .... 10 L 10


1 Printing .... 11 L 9
1 Printing .... 12 L 9
1 Printing .... 13 L 9
1 Printing .... 14 L 9
1 Printing .... 15 L 9
1 Printing .... 16 L 9
1 Printing .... 17 L 9
1 Printing .... 18 L 9
1 Printing .... 19 L 9
1 Printing .... 20 L 9

and So on ... 
2 Printing .... 21 L 8
2 Printing .... 22 L 8
2 Printing .... 23 L 8

随着闩锁的每个递减计数器,下一个线程是池必须 执行计数直到 10。然后它必须再次减少锁存器 计数器并再次重复该过程,直到线程 9 完成 一样的

请提出一些意见。

【问题讨论】:

  • 您是否要等待所有作业完成?这里的目标是什么?

标签: java multithreading executorservice


【解决方案1】:

因此,您正在配置 10 new CountDownLatch(10) 的倒计时值,但您的代码仅在每个线程中递减一次。在你只 fork 1 个线程之后,你等待闩锁,但它位于 9。

MyThread thread = new MyThread(i*10, ""+i,latch);
exec.execute(thread);
latch.await();

不确定您的意图,但也许 latch.countDown(); 应该线程中的 for 循环中?

for(int i=0;i<10;i++) {
   ...
   // if you want the latch to count-down 10 times, it should be inside the loop
   latch.countDown();
}
// it should not go here, outside the loop

如果目标是等待所有作业完成,您可以使用ExecutorService.awaitTermination(...) 方法来完成:

// submit jobs in loop
exec.shutdown();
exec.awaitTermination(Long.MAX_VALUE, TimeUnit.MILLISECONDS);

另外,您应该在您的 MyThread 类中扩展 Thread。您应该实施Runnable。您的代码有效的唯一原因是Thread 也实现了Runnable,但MyThread 应该ThreadExecutorService 采用 RunnableCallable,而不是 Thread。它在服务内部为您管理线程。

【讨论】:

  • 我已经更新了我的预期输出,并感谢关于 runnable 的建议。
  • @Gray 一定在这里说过一百万次了 :)
  • 不可能@RalfH。 100k 顶! ;-)
【解决方案2】:

如果您的意图是使用CountDownLatchmain() 方法等到所有线程都执行完毕,那么您应该将latch.await() 移出 提交线程的循环。 此外,如果没有再次设置中断标志,您不应该吃InterruptedException。 (see this article)。

更正如下所示:

for(int i=0;i<10;i++){          
    MyThread thread = new MyThread(i*10, ""+i,latch);
    exec.execute(thread);
}
try {
    latch.await();
} catch (InterruptedException e) {
    Thread.currentThread().interrupt();
}

虽然这肯定会起作用,但是当使用ExecutorService 时,Latch 是等待另一个线程上的 Runnable 执行的次优方式。如果你使用submit()而不是execute(),你可以使用submit()返回的Future,通过调用get()来等待提交的Runnable完成。

【讨论】:

    【解决方案3】:

    感谢大家的投入。 我找到了一种更简单的解决方案来达到我的预期。 我刚刚使用了Executors.newSingleThreadExecutor();,因为它已经确保所有任务都会保证按顺序执行。

    【讨论】:

      猜你喜欢
      • 2017-01-30
      • 1970-01-01
      • 2017-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多