我正在尝试使用Java的ThreadPoolExecutor类来运行具有固定数量线程的大量重量级任务.每个任务都有许多地方,在这些地方可能因异常而失败.
我已经进行了子类化,ThreadPoolExecutor并且我已经覆盖了该afterExecute方法,该方法应该在运行任务时提供任何未捕获的异常.但是,我似乎无法使其发挥作用.
例如:
public class ThreadPoolErrors extends ThreadPoolExecutor {
public ThreadPoolErrors() {
super( 1, // core threads
1, // max threads
1, // timeout
TimeUnit.MINUTES, // timeout units
new LinkedBlockingQueue<Runnable>() // work queue
);
}
protected void afterExecute(Runnable r, Throwable t) {
super.afterExecute(r, t);
if(t != null) {
System.out.println("Got an error: " + t);
} else {
System.out.println("Everything's fine--situation normal!");
}
}
public static void main( String [] args) {
ThreadPoolErrors threadPool = new …Run Code Online (Sandbox Code Playgroud) java multithreading exception executorservice threadpoolexecutor
newCachedThreadPool() 与 newFixedThreadPool()
我什么时候应该使用其中一种?哪种策略在资源利用方面更好?
java concurrency multithreading executorservice threadpoolexecutor
似乎不可能创建一个缓存的线程池,它可以创建的线程数限制.
以下是在标准Java库中实现静态Executors.newCachedThreadPool的方法:
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
Run Code Online (Sandbox Code Playgroud)
因此,使用该模板继续创建固定大小的缓存线程池:
new ThreadPoolExecutor(0, 3, 60L, TimeUnit.SECONDS, new SynchronusQueue<Runable>());
Run Code Online (Sandbox Code Playgroud)
现在,如果你使用它并提交3个任务,一切都会好的.提交任何进一步的任务将导致被拒绝的执行异常.
试试这个:
new ThreadPoolExecutor(0, 3, 60L, TimeUnit.SECONDS, new LinkedBlockingQueue<Runable>());
Run Code Online (Sandbox Code Playgroud)
将导致所有线程按顺序执行.即,线程池永远不会有多个线程来处理您的任务.
这是ThreadPoolExecutor的execute方法中的错误?或者这可能是故意的?还是有其他方式?
编辑:我想要一些与缓存线程池完全相同的东西(它根据需要创建线程,然后在一些超时后杀死它们)但是它可以创建的线程数量受到限制,并且一旦有了它就能够继续排队其他任务达到了它的线程限制.根据sjlee的回应,这是不可能的.查看ThreadPoolExecutor的execute()方法确实是不可能的.我需要继承ThreadPoolExecutor并覆盖execute(),就像SwingWorker一样,但SwingWorker在其execute()中所做的是一个完整的hack.
java concurrency multithreading executorservice threadpoolexecutor
我已经沮丧了一段时间,其默认行为ThreadPoolExecutor支持ExecutorService我们这么多人使用的线程池.引用Javadocs:
如果有多个corePoolSize但运行的maximumPoolSize线程少于maximumPoolSize,则只有在队列已满时才会创建新线程.
这意味着如果您使用以下代码定义线程池,它将永远不会启动第二个线程,因为它LinkedBlockingQueue是无限制的.
ExecutorService threadPool =
new ThreadPoolExecutor(1 /*core*/, 50 /*max*/, 60 /*timeout*/,
TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(/* unlimited queue */));
Run Code Online (Sandbox Code Playgroud)
只有当您有一个有界队列并且队列已满时才会启动核心编号之上的任何线程.我怀疑大量的初级Java多线程程序员并不知道这种行为ThreadPoolExecutor.
现在我有一个特定的用例,这不是最佳的.我正在寻找方法,而不是编写我自己的TPE课程来解决它.
我的要求是针对可能不可靠的第三方回拨的Web服务.
newFixedThreadPool(...)大量的线程,大多数都处于休眠状态.newCachedThreadPool().在更多线程启动之前,如何解决ThreadPoolExecutor队列需要限制和填充的限制?如何让它在排队任务之前启动更多线程?
编辑:
@Flavio提出了使用ThreadPoolExecutor.allowCoreThreadTimeOut(true)核心线程超时并退出的好处.我考虑过这一点,但我仍然想要核心线程功能.如果可能的话,我不希望池中的线程数降到核心大小以下.
当我们谈论ThreadPoolExecutor时,核心池大小和最大池大小之间究竟有什么区别?可以借助一个例子来解释吗?
我无法使用shutdown(),awaitTermination()因为有可能在等待时将新任务添加到ThreadPoolExecutor中.
所以我正在寻找一种方法,等待ThreadPoolExecutor清空它的队列并完成所有任务而不停止在该点之前添加新任务.
如果它有任何区别,这适用于Android.
谢谢
更新:几周后重新访问后,我发现在这种情况下修改后的CountDownLatch对我来说效果更好.我会保留答案标记,因为它更适用于我的要求.
我正在开发一个多线程项目,我需要生成多个线程来测量我的客户端代码的端到端性能,因为我正在进行负载和性能测试.所以我创建了以下使用的代码ExecutorService.
以下是代码ExecutorService:
public class MultithreadingExample {
public static void main(String[] args) throws InterruptedException {
ExecutorService executor = Executors.newFixedThreadPool(20);
for (int i = 0; i < 100; i++) {
executor.submit(new NewTask());
}
executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);
}
}
class NewTask implements Runnable {
@Override
public void run() {
//Measure the end to end latency of my client code
}
}
Run Code Online (Sandbox Code Playgroud)
问题陈述:
现在我正在阅读互联网上的一些文章.我发现也有ThreadPoolExecutor.所以我很困惑我应该使用哪一个.
如果我将以上代码替换为:
ExecutorService executor = Executors.newFixedThreadPool(20);
for (int i = 0; i < 100; i++) …Run Code Online (Sandbox Code Playgroud) java multithreading executorservice blockingqueue threadpoolexecutor
Java 5引入了Executor框架形式的线程池对异步任务执行的支持,其核心是java.util.concurrent.ThreadPoolExecutor实现的线程池.Java 7以java.util.concurrent.ForkJoinPool的形式添加了一个备用线程池.
查看各自的API,ForkJoinPool在标准场景中提供了ThreadPoolExecutor功能的超集(虽然严格来说ThreadPoolExecutor提供了比ForkJoinPool更多的调优机会).除此之外,fork/join任务看起来更快(可能是因为工作窃取调度程序)的观察结果显然需要更少的线程(由于非阻塞连接操作),可能会让人觉得ThreadPoolExecutor已被取代ForkJoinPool.
但这真的是对的吗?我读过的所有材料似乎总结为两种类型的线程池之间相当模糊的区别:
这种区别是否正确?我们能说出更具体的内容吗?
java parallel-processing threadpool threadpoolexecutor forkjoinpool
我ThreadPoolExecutor无法创建新线程.事实上,我写了一个有点hacky LinkedBlockingQueue,它将接受任何任务(即它是无限制的)但是调用一个额外的处理程序 - 在我的应用程序中喷出警告跟踪池后面 - 这给了我非常明确的信息,TPE拒绝创建新线程,即使队列中有数千个条目.我的构造函数如下:
private final ExecutorService s3UploadPool =
new ThreadPoolExecutor(1, 40, 1, TimeUnit.HOURS, unboundedLoggingQueue);
Run Code Online (Sandbox Code Playgroud)
为什么不创建新线程?
我有一个Web服务器服务,客户端请求智能卡计算并获得结果.可用的智能卡号可以在服务器正常运行时间内减少或增加,例如我可以从阅读器中物理添加或删除智能卡(或许多其他事件......例如异常等).
智能卡计算可能需要一段时间,因此如果存在对Web服务器的并发请求,我必须优化这些作业以使用所有可用的智能卡.
我想过使用智能卡线程池.至少对我而言,不寻常的是,池应该改变其大小,而不是取决于客户端请求,而只取决于智能卡的可用性.
我研究过很多例子:
这是智能卡控件,每个智能卡有一个SmartcardWrapper,每个智能卡都有自己的插槽号.
public class SmartcardWrapper{
private int slot;
public SmartcardWrapper(int slot) {
this.slot=slot;
}
public byte[] compute(byte[] input) {
byte[] out=new byte[];
SmartcardApi.computerInput(slot,input,out); //Native method
return out;
}
}
Run Code Online (Sandbox Code Playgroud)
我尝试使用每个智能卡一个线程创建一个线程池:
private class SmartcardThread extends Thread{
protected SmartcardWrapper sw;
public SmartcardThread(SmartcardWrapper sw){
this.sw=sw;
}
@Override
public void run() {
while(true){
byte[] input=queue.take();
byte output=sw.compute(input);
// I have to return back the output to the client
}
}
} …Run Code Online (Sandbox Code Playgroud) java concurrency multithreading smartcard threadpoolexecutor
java ×9
concurrency ×3
threadpool ×2
android ×1
exception ×1
forkjoinpool ×1
smartcard ×1
wait ×1