我是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然后程序应该停止。
我认为countdownlatch正在等待并等待它不会增加执行者的下一个计数器。所以我无法得到预期的输出。 我期待输出像 -
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
与latch的每个递减计数器,下一个线程是池必须 执行计数直到10.然后再次必须减少锁存器 计数器再次重复该过程直到线程9完成 相同
请提出一些意见。
答案 0 :(得分:3)
因此,您正在配置倒计时值10 new CountDownLatch(10)
,但您的代码只是每个线程减少一次。在你只分叉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);
此外,不应该在Thread
课程中展开MyThread
。您应该实施Runnable
。您的代码有效的唯一原因是Thread
也实现了Runnable
,但MyThread
应该不是Thread
。 ExecutorService
需要Runnable
或Callable
,而不是Thread
。它在内部管理服务的线程。
答案 1 :(得分:1)
如果您打算使用CountDownLatch
让main()
方法等到所有线程都执行完毕,那么您应该将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()
,则可以使用Future
返回的submit()
,通过调用Runnable
等待提交的get()
完成在它上面。
答案 2 :(得分:0)
感谢大家的投入。
我找到了一个更简单的解决方案来达到我的预期。
我刚刚使用Executors.newSingleThreadExecutor();
,因为它已经确保所有任务都能保证按顺序实现。