我有一个带有250个条目的队列的线程池,每秒我都会推送每60个任务。通常,任务运行得非常快,但如果某些条件满足,则需要执行长时间运行的任务。正常任务运行现在被阻止,因为正在执行长时间运行的任务。
执行时间是否可以分割一个Runnable的执行(在需要长时间运行的任务的情况下)?
换句话说:我喜欢异步启动长时间运行的任务,但我不想创建太多的线程,因为在那种情况下我会因为线程通信而得到开销。我可以使用ForkJoinPool吗?还是我必须分开长期和短期运行任务来解决这个问题?
我的机器有4个核心:
ExecutorService queue = new ThreadPoolExecutor(2,
4,
400,
TimeUnit.MILLISECONDS,
new ArrayBlockingQueue<Runnable>(250, true),
new ThreadPoolExecutor.DiscardOldestPolicy());
Runnable r = new Runnable() {
@Override
public void run() {
try {
if(isTimeForLongRunningExecution()){
//Is it possible to start this job asynchronous without starting to many threads
doLongRunningTask();
}//do job with old data until new data is available, but do not block this operation too long
doNormalTaskWithOldOrNewData();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
private void doNormalTaskWithOldOrNewData() throws InterruptedException {
if(checkNewDataAvailable()){
System.out.println("Work with new Data");
Thread.sleep(300L);
System.out.println("Work completed!");
}else{
System.out.println("Work with old Data");
Thread.sleep(300L);
System.out.println("Work completed!");
}
}
private void doLongRunningTask() throws InterruptedException {
System.out.println("Create new Data");
Thread.sleep(3*60*1000L);
System.out.println("Data creation completed!");
}
};//end of runnable
while(true){
for (int i = 0; i < 60; i++) {
queue.submit(r);
}
Thread.sleep(1000);
}
答案 0 :(得分:0)
这是一项有趣的任务,但我并不了解你想要达到的目标。你正在给出一个解决方案,但你没有告诉我们问题是什么,因为这里有很多人可以建议你一个更合适的解决方案。
无论如何,我建议您下载并使用VisualVM。
如果您尚未使用它,请监控性能并查看延迟的位置。在过去,我发现理解线程在哪里等待非常有用(你有同步代码吗?)。
为什么不尝试在与Normal任务分开的Thread中启动长时间运行的任务?
另请查看Executors.newCachedThreadPool()
,因为执行许多short-lived asynchronous tasks非常好。
最后,如果你还没有这样做,我还建议给性能计时并看看自己如何改善/变得更糟,或者使用其他一些指标(将普通线程读取新数据的次数存储在某处) ,旧数据)。
答案 1 :(得分:0)
使用2 ordinary thread pools - 一个用于快速,另一个用于长时间运行的任务。让每个线程池拥有与处理器核心一样多的线程。将所有任务提交到快速线程池。让任务,如果它发现需要长时间工作,则将另一个任务提交给长线程池并退出。
答案 2 :(得分:0)
我想到的最简单的解决方案是使用两个队列。其中一个是短期生活任务,一个是长期生活任务的无限期。
您也可以使用自己的线程创建例程构造Executor,并确保所有这些长生命线程都以低优先级运行,因此它们不会干扰短期任务。
final Executor longLivingTasksExecutor = Executors.newCachedThreadPool(new PriorityThreadFactory(Thread.MIN_PRIORITY));
PriorityThreadFactory
是我自己写的课程:
public class PriorityThreadFactory implements ThreadFactory, ForkJoinPool.ForkJoinWorkerThreadFactory {
protected final ThreadGroup allThreads;
protected final int priority;
public PriorityThreadFactory(final String name, final int priority, final boolean daemon) {
this.priority = priority;
this.allThreads = new ThreadGroup(name);
this.allThreads.setMaxPriority(priority);
this.allThreads.setDaemon(daemon);
}
public PriorityThreadFactory(final int priority, final boolean daemon) {
this("workers", priority, daemon);
}
public PriorityThreadFactory(final int priority) {
this("workers", priority, false);
}
@Override
public Thread newThread(final Runnable r) {
return new Thread(this.allThreads, r);
}
@Override
public ForkJoinWorkerThread newThread(final ForkJoinPool pool) {
final ForkJoinWorkerThread result = ForkJoinPool.defaultForkJoinWorkerThreadFactory.newThread(pool);
result.setPriority(priority);
return result;
}
}