所以,我很好奇。如何处理为线程设置最长执行时间?在线程池中运行时?
我有几种技巧,但我对它们并不十分满意。所以,我想我会问社区他们是怎么回事。
答案 0 :(得分:5)
怎么样:
将您的Callable
提交至ExecutorService
,并处理返回的Future
。
ExecutorService executorService = ... // Create ExecutorService.
Callable<Result> callable = new MyCallable(); // Create work to be done.
Future<Result> fut = executorService.submit(callable);
将Future
包含在Delayed
的实现中,其中Delayed
的{{1}}方法返回相关作品的最长执行时间。
getDelay(TimeUnit)
从队列中重复一个帖子public class DelayedImpl<T> implements Delayed {
private final long maxExecTimeMillis;
private final Future<T> future;
public DelayedImpl(long maxExecTimeMillis, Future<T> future) {
this.maxExecMillis = maxExecMillis;
this.future = future;
}
public TimeUnit getDelay(TimeUnit timeUnit) {
return timeUnit.convert(maxExecTimeMillis, TimeUnit.MILLISECONDS);
}
public Future<T> getFuture() {
return future;
}
}
DelayedImpl impl = new DelayedImpl(3000L, fut); // Max exec. time == 3000ms.
Add the `DelayedImpl` to a `DelayQueue`.
Queue<DelayedImpl> queue = new DelayQueue<DelayImpl>();
queue.add(impl);
,并通过调用take()
检查每个DelayedImpl
的{{1}}是否完整;如果没有,则取消该任务。
Future
此方法的主要优点是您可以为每个任务设置不同的最大执行时间,延迟队列将自动以最少的执行时间返回任务。
答案 1 :(得分:4)
Adamski的:
我认为您的延迟接口实现需要进行一些调整才能正常工作。如果从对象实例化开始所经过的时间量超过最大生命周期,则'getDelay()'的返回值应返回负值。要实现这一点,您需要存储创建任务的时间(并且可能已启动)。然后每次调用'getDelay()'时,计算是否超过了线程的最大生命周期。如:
class DelayedImpl<T> implements Delayed {
private Future<T> task;
private final long maxExecTimeMinutes = MAX_THREAD_LIFE_MINUTES;
private final long startInMillis = System.currentTimeMillis();
private DelayedImpl(Future<T> task) {
this.task = task;
}
public long getDelay(TimeUnit unit) {
return unit.convert((startInMillis + maxExecTimeMinutes*60*1000) - System.currentTimeMillis(), TimeUnit.MILLISECONDS);
}
public int compareTo(Delayed o) {
Long thisDelay = getDelay(TimeUnit.MILLISECONDS);
Long thatDelay = o.getDelay(TimeUnit.MILLISECONDS);
return thisDelay.compareTo(thatDelay);
}
public Future<T> getTask() {
return task;
}
}
答案 2 :(得分:3)
通常,我只是从线程代码中定期轮询一个控制对象。类似的东西:
interface ThreadControl {
boolean shouldContinue();
}
class Timer implements ThreadControl {
public boolean shouldContinue() {
// returns false if max_time has elapsed
}
}
class MyTask implements Runnable {
private tc;
public MyTask(ThreadControl tc) {
this.tc = tc;
}
public void run() {
while (true) {
// do stuff
if (!tc.shouldContinue())
break;
}
}
}