有没有办法在Executor Services上设置最长等待时间?!
例如,当你传递两个而真正的runnable传递给SingleThreadExecutor
时,第一个将永远工作,而第二个将永远等待。
我希望得到关于第二个Runnable的TimeOutException。
public static void main(String[] args) throws IOException {
ExecutorService executor = Executors.newSingleThreadExecutor();
for (int i = 0; i < 2; i++) {
int finalI = i;
executor.execute(new Runnable() {
@Override
public void run() {
while (true) {
try {
System.out.println("#"+ finalI + " Runnable !");
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
});
}
}
答案 0 :(得分:1)
您的执行者只有一个帖子。它将在内部对不同的Runnable任务进行排队,并尝试逐个完成它们。如果第一个任务永远不会完成(因为它是一个真正的循环),第二个任务将永远不会启动。
您可以使用submit
代替execute
来获取Future对象,并执行get
操作,而不是超时。
public static void main(String[] args) throws IOException {
ExecutorService executor = Executors.newSingleThreadExecutor();
List<Future> future = new ArrayList<>();
for (int i = 0; i < 2; i++) {
int finalI = i;
future.add(executor.submit(new Runnable() {
@Override
public void run() {
while (true) {
try {
System.out.println("#"+ finalI + " Runnable !");
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}));
}
// Check if second task finishes in the next 2 seconds, and throw a TimeoutException if it does not
try {
future.get(1).get(2000, TimeUnit.MILLISECONDS);
} catch (TimeoutException e) {
e.printStackTrace();
}
}
确定您的任务超时后,您可以使用future.get(1).cancel(false)
但是,如果在每个线程繁忙时拒绝任务,则可以尝试这种方法:
BlockingQueue<Runnable> queue = new SynchronousQueue<>();
ExecutorService executorService = new ThreadPoolExecutor(2, 2,
0L, TimeUnit.MILLISECONDS,
queue);
如果所有线程都忙,ExecutorService将自动拒绝任务。
答案 1 :(得分:1)
有没有办法在Executor Services上设置最长等待时间?!
如果你在谈论等待工作开始运行,不幸的是答案是“不容易”。有一些方法可以使用ThreadPoolExecutor
中的队列来执行此操作,但它们将被视为黑客攻击,不建议使用。您也可以扩展ThreadPoolExecutor
,但这可能会变得复杂。
一个[更好]的解决方案是在外部管理你的队列。
// synchronous queue waits for someone to take() from the queue before returning
final BlockingQueue<Runnable> jobQueue = new SynchronousQueue<Runnable>();
...
// submit all of your threads who get jobs from your queue to run
executor.execute(new Runnable() {
@Override
public void run() {
while (!Thread.currentThread.isInterrupted()) {
try {
Runnable job = jobQueue.take();
job.run();
} catch (InterruptedException ie) {
// always recommended
Thread.currentThread().interrupt();
return;
}
}
}
});
...
// now we can try to add a job into the queue but if it is full, offer may timeout
if (!queue.offer(new Runnable() { ... }, 2000, TimeUnit.SECONDS)) {
// timed out
}
希望这有帮助。