在我的webapp中,我创建了一个ExecutorService使用固定大小的ThreadPool的服务.我ExecutorService在整个应用程序生命周期中重复使用它.
private static ExecutorService pool = Executors.newFixedThreadPool(8);
Run Code Online (Sandbox Code Playgroud)
所有都在Tomcat中运行,它在向下发出错误时给出了以下错误:
appears to have started a thread named [pool-1-thread-1] but has failed to stop it. This is very likely to create a memory leak.
Run Code Online (Sandbox Code Playgroud)
我确实意识到我需要在关闭tomcat之前关闭ExecutorService.Soms SO线程已经谈到了这一点,但我找不到一个干净的方法来处理这个问题.
我是否应该ShutdownHook在线程和执行程序的正常关闭中使用@ Tim-bender ?或者我应该使用CachedThreadPool吗?
ExecutorService pool=Executors.newFixedThreadPool(7);
List<Future<Hotel>> future=new ArrayList<Future<Hotel>>();
List<Callable<Hotel>> callList = new ArrayList<Callable<Hotel>>();
for(int i=0;i<=diff;i++){
String str="2013-"+(liDates.get(i).get(Calendar.MONTH)+1)+"-"+liDates.get(i).get(Calendar.DATE);
callList.add(new HotelCheapestFare(str));
}
future=pool.invokeAll(callList);
for(int i=0;i<=future.size();i++){
System.out.println("name is:"+future.get(i).get().getName());
}
Run Code Online (Sandbox Code Playgroud)
现在我想invokeAll在进入for循环之前将pool放到所有任务中,但是当我运行这个程序for循环时,在此之前执行invokeAll并抛出此异常:
java.util.concurrent.ExecutionException: java.lang.NullPointerException at
java.util.concurrent.FutureTask$Sync.innerGet(Unknown Source) at
java.util.concurrent.FutureTask.get(Unknown Source) at
com.mmt.freedom.cheapestfare.TestHotel.main(TestHotel.java:6??5)
Caused by: java.lang.NullPointerException at
com.mmt.freedom.cheapestfare.HotelCheapestFare.getHotelCheap?estFare(HotelCheapes??tFare.java:166)
at com.mmt.freedom.cheapestfare.HotelCheapestFare.call(HotelChe??apestFare.java:219)
at com.mmt.freedom.cheapestfare.HotelCheapestFare.call(HotelChe??apestFare.java:1)
at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source) at java.util.concurrent.FutureTask.run(Unknown Source)
at java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source) atjava.util.concurrent.ThreadPoolExecutor$Worker.run(Unknow??n Source)
at java.lang.Thread.run
Run Code Online (Sandbox Code Playgroud) 我有一个关于如何ExecutorService在Java中工作的基本问题.
很难看出简单地创建Threads并行执行某些任务和将每个任务分配给它们之间的区别ThreadPool.
使用起来ExecutorService也非常简单和有效,所以我想知道为什么我们不一直使用它.
这只是一种比另一种方式更快地执行其工作的问题吗?
这里有两个非常简单的例子来说明两种方式之间的区别:
使用执行程序服务:Hello World(任务)
static class HelloTask implements Runnable {
String msg;
public HelloTask(String msg) {
this.msg = msg;
}
public void run() {
long id = Thread.currentThread().getId();
System.out.println(msg + " from thread:" + id);
}
}
Run Code Online (Sandbox Code Playgroud)
使用执行程序服务:Hello World(创建执行程序,提交)
static class HelloTask {
public static void main(String[] args) {
int ntasks = 1000;
ExecutorService exs = Executors.newFixedThreadPool(4);
for (int i=0; i<ntasks; i++) {
HelloTask t = new HelloTask("Hello from …Run Code Online (Sandbox Code Playgroud) 在发现在Java 1.6上FutureTask运行Executors.newCachedThreadPool()(以及从Eclipse中)吞下Runnable.run()方法中的异常后,我试图找到一种方法来捕获这些,而不向我的所有Runnable实现添加throw/catch .
API建议覆盖FutureTask.setException()应该有助于此:
导致此未来报告ExecutionException,并将给定的throwable作为其原因,除非已设置或已取消此Future.在计算失败时,run方法在内部调用此方法.
但是,似乎没有调用此方法(使用调试器运行显示异常被捕获FutureTask但setException未被调用).我写了以下程序来重现我的问题:
public class RunTest {
public static void main(String[] args) {
MyFutureTask t = new MyFutureTask(new Runnable() {
@Override
public void run() {
throw new RuntimeException("Unchecked exception");
}
});
ExecutorService service = Executors.newCachedThreadPool();
service.submit(t);
}
}
public class MyFutureTask extends FutureTask<Object> {
public MyFutureTask(Runnable r) {
super(r, null);
}
@Override
protected void setException(Throwable t) {
super.setException(t);
System.out.println("Exception: " + t);
} …Run Code Online (Sandbox Code Playgroud) 在ScheduledExecutorService中运行时,是否有一种很好的方法可以阻止任务内部重复任务?
可以说,我有以下任务:
Future<?> f = scheduledExecutor.scheduleAtFixedRate(new Runnable() {
int count = 0;
public void run() {
System.out.println(count++);
if (count == 10) {
// ??? cancel self
}
}
}, 1, 1, TimeUnit.SECONDS);
Run Code Online (Sandbox Code Playgroud)
从外面看,很容易通过f.cancel()取消,但是如何在指定的地方停止重复?(通过AtomicReference传递Future是不安全的,因为当scheduleAtFixedRate返回f迟到且变量设置得太晚时,有一个潜在的窗口,并且任务本身可能已经运行,在引用中看到null.)
java concurrency anonymous-class executorservice variable-initialization
我向Java中的executorservice提交了大量工作,我想以某种方式暂时暂停所有这些工作.最好的方法是什么?我该如何恢复?或者我这样做完全错了?我应该遵循一些其他模式来实现我想要达到的目标(即暂停/恢复执行服务的能力)吗?
java parallel-processing concurrency multithreading executorservice
一个执行器对象是否意味着在一个shutdown?之后重用?我的意思是,如果我调用shutdown或shutdownNow在执行程序终止后,我应该new创建一个新的线程池,还是可以以某种方式"重置"/重用以前终止的执行程序并重用它?
更新:
如果我需要创建新的线程池,我怎么能"理解"前一个已停止?
例如以下内容:
public void startPool(){
if(threadPool != null && !threadPool.isShutdown()){
return;
}
threadPool = Executors.newCachedThreadPool();
//other stuff
}
public void stopPool(){
if(threadPool != null){
threadPool.shutdown();
}
}
Run Code Online (Sandbox Code Playgroud)
不管用.如果我调用stop然后start由于条件将不会创建新的线程池.编码的正确方法是什么?
我有一个新手问题.我有这个代码:
public class Main
{
public static void main(String[] args) throws InterruptedException
{
// TODO Auto-generated method stub
IntHolder aHolder=new IntHolder();
aHolder.Number=0;
IncrementorThread A= new IncrementorThread(1, aHolder);
IncrementorThread B= new IncrementorThread(2, aHolder);
IncrementorThread C= new IncrementorThread(3, aHolder);
A.start();
B.start();
C.start();
A.join();
B.join();
C.join();
System.out.println("All threads completed...");
}
}
Run Code Online (Sandbox Code Playgroud)
这将等待所有线程完成.如果我这样使用Executors:
public class Main
{
public static void main(String[] args)
{
// TODO Auto-generated method stub
IntHolder aHolder=new IntHolder();
aHolder.number=0;
IncrementalRunable A= new IncrementalRunable(1, aHolder);
IncrementalRunable B= new IncrementalRunable(2, aHolder); …Run Code Online (Sandbox Code Playgroud) 我用一个固定大小的线程池Executors.newFixedThreadPool(2),我执行了10个Runnable对象.我设置断点并追踪执行.但是,fixedSizeThreadPool.awaitTermination()即使完成了所有任务,也不允许我继续.
基本上:
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2);
for (int i = 0; i < 10; ++i) {
fixedSizeThreadPool.execute(myRunables[i]);
}
try {
fixedSizeThreadPool.awaitTermination(timeout, timeoutUnits);
} catch (Exception e) { }
System.out.println("done!");
Run Code Online (Sandbox Code Playgroud)
但这总是被困住awaitTermination.怎么了?
我对按顺序关闭调度的线程的想法很满意ExectuorService; 也就是说,调用shutdown或shutdownNow将导致池上创建的线程正常退出.如果他们回复interrupt你,你可以确定最终会被调用等等,你会得到一个干净,可预测的退出(你可以清理任何资源等).
但是,如果您已将线程设置为守护程序(通过执行程序ThreadFactory),如下所示.
ExecutorService pool = Executors.newSingleThreadExecutor(new ThreadFactory() {
@Override
public Thread newThread(Runnable runnable) {
Thread thread = Executors.defaultThreadFactory().newThread(runnable);
thread.setDaemon(true);
return thread;
}
});
Run Code Online (Sandbox Code Playgroud)
主线程终止后,VM将突然终止任何守护程序线程.在上面的示例中,调度然后突然终止的(守护进程)线程将绕过任何finally块,并且任何可中断的方法都不会抛出InterruptedException.
所以,我倾向于认为,这标志着一个使用线程ThreadPoolExecutor的池守护进程是不好的做法...我的问题是真的请他帮我练声曲为什么.
为什么在ExecutorService线程池中使用守护程序线程是不好的做法(或者如果你不同意)?特别是我有兴趣通过正常关闭(具有中断策略并且运行良好的线程)与守护程序线程来描述VM关闭的生命周期.
扩展最后一点,finalizeon ThreadPoolExecutor将调用shutdown自身,但是当它使用守护程序线程时,如果finalizeVM调用它们,它们可能已经终止.那么线程池的行为是什么呢?如果底层线程突然终止,它是否可以被欺骗以保持活着(因此不会退出VM)?
我问的部分原因是因为我已经看到它曾经绕过了关闭实际的ExectorService的需要.您能想到绕过其关闭生命周期会产生不良影响的情况吗?到目前为止,我可以提出使用守护进程的唯一原因是采取捷径,我想欣赏它可能导致的任何意外的副作用.
executorservice ×10
java ×10
concurrency ×5
arraylist ×1
daemon ×1
future ×1
futuretask ×1
tomcat6 ×1