由于某种原因,java.util.concurrent.ExecutorCompletionService
未使用java.util.concurrent.ExecutorService
线程池中的线程。这会影响ExecutorCompletionService.submit()
方法调用的“阻塞”执行。请考虑以下代码:
package completionservicedemo1;
import java.util.Date;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
public class CompletionServiceDemo1 {
static final ExecutorService executor = Executors.newFixedThreadPool(10, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setName("Executor-Thread");
try {
System.out.println("Thread going to sleep: "+Thread.currentThread().getName());
thread.sleep(5000L);
System.out.println("Thread awakened: "+Thread.currentThread().getName());
} catch (InterruptedException ex) {
System.out.println("InteruptedException: "+ex);
}
return thread;
}
});
static final ExecutorCompletionService<String> completionService = new ExecutorCompletionService<>(executor);
static byte val=1;
public static void main(String[] args) throws InterruptedException, ExecutionException {
System.out.println("App start time: "+ new Date());
completionService.submit(()->"String"+ ++val);
System.out.println("All tasks submitted at: "+ new Date());
}
}
输出:
应用开始时间:2016年1月5日星期二00:20:27 IST 2016
线程进入睡眠状态:主
线程被唤醒:主要
所有任务提交于:2016年1月5日00:20:32 IST 2016
很明显,ExecutorCompletionStage没有使用ExecutorService池中的线程,因此completionService.submit(()->"String"+ ++val);
会在延迟5秒后响应。
理想情况下,submit()方法应将传递的Callable实例任务提交到ExecutorService池以进行并发执行。但这显然不会发生,因为输出中的线程名称显示。
有人可以解释一下这里发生的事情吗?为什么不同时在ExecutorService线程池上计算Callable?为什么completionService.submit()阻塞(5s)?
答案 0 :(得分:5)
为什么
ExecutorCompletionService
不使用ExecutorService
池中的线程?
确实如此。见结束答案。
javadoc of newFixedThreadPool
州
使用提供的
ThreadFactory
在需要时创建新线程
换句话说,返回的ExecutorService
个线程是根据需要懒惰地创建newThread
的。
提交任务时
completionService.submit(()->"String"+ ++val);
没有Thread
个实例可用于接受任务。因此,ExecutorService
将使用newThread
创建新主题。它在调用线程main
中执行此操作。由于您的newThread
已实现睡眠5秒,这正是它的作用。 sleep
完成后,newThread
将返回Thread
实例,ExecutorService
将启动并执行提交的
()->"String"+ ++val
请注意,您的任务仅连接String
和int
值并返回结果。
将其更改为
Future<String> future = completionService.submit(() -> "String" + ++val + " Thread " + Thread.currentThread());
System.out.println("All tasks submitted at: " + new Date());
System.out.println("Future returned: " + future.get());
在返回的get
上调用Future
以等待其完成并看到有用的内容。
答案 1 :(得分:0)
阅读@Sotirios Delimanolis&#39;回复,我能够解决我的问题,并了解问题。我错误地搜索了将在ThreadFactory.newThread()
内执行Callable而不是Callable.call()
方法的工作线程名称。在解决这个案例后,一切都是连贯的:
package completionservicedemo1;
import java.util.Date;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.ThreadFactory;
public class CompletionServiceDemo1 {
static final ExecutorService executor = Executors.newFixedThreadPool(10, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread thread = new Thread(r);
thread.setName("Executor-Thread");
try {
System.out.println("Thread going to sleep: "+Thread.currentThread().getName());
thread.sleep(1000L);
System.out.println("Thread awakened: "+Thread.currentThread().getName());
} catch (InterruptedException ex) {
System.out.println("InteruptedException: "+ex);
}
return thread;
}
});
static final ExecutorCompletionService<String> completionService = new ExecutorCompletionService<>(executor);
static byte val=1;
public static void main(String[] args) throws InterruptedException, ExecutionException {
System.out.println("App start time: "+ new Date());
completionService.submit(()->{
System.out.println("Thread executing the callable: "+Thread.currentThread().getName()+" "+new Date());
Thread.sleep(10000L);
System.out.println("Worker Thread came out of sleep: "+Thread.currentThread().getName()+" "+new Date());
return "String"+ ++val;
});
System.out.println("All tasks submitted at: "+ new Date());
System.out.println("main thread taking completed future at: "+new Date());
//following would block on the BlockingQue as there is a 10s delay
Future<String> resultingFuture = completionService.take();
//following would not block since only completed Futures are placed on the BlockingQue (by QueueingFuture)
System.out.println("result: "+resultingFuture.get());
System.out.println("main thread got completed future result at: "+new Date());
}
}
输出:
应用开始时间:2016年1月5日星期二08:00:06
线程进入睡眠状态:主
线程被唤醒:主要
所有任务提交时间:2016年1月5日08:00:07 IST 2016
主线程完成未来:2016年1月5日08:00:07 IST 2016
线程执行callable:Executor-Thread Tue Jan 05 08:00:07 IST 2016
工人线程从睡眠中醒来:Executor-Thread Tue Jan 05 08:00:17 IST 2016
结果:String2
主线程已完成未来结果:Tue Jan 05 08:00:17 IST 2016