处理线程最大执行时间的最佳方法(Java)

处理线程最大执行时间的最佳方法(Java),java,concurrency,multithreading,Java,Concurrency,Multithreading,所以,我很好奇。如何设置线程的最大执行时间?在线程池中运行时 我有几种技巧,但我从来都不太满意。所以,我想我应该问问社区他们是怎么做的。通常,我只是定期从线程代码中轮询一个控件对象。比如: interface ThreadControl { boolean shouldContinue(); } class Timer implements ThreadControl { public boolean shouldContinue() { // returns

所以,我很好奇。如何设置线程的最大执行时间?在线程池中运行时


我有几种技巧,但我从来都不太满意。所以,我想我应该问问社区他们是怎么做的。

通常,我只是定期从线程代码中轮询一个控件对象。比如:

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;
        }
    }
}
那么:

将您的
Callable
提交给
ExecutorService
,并保留返回的
将来的
句柄

ExecutorService executorService = ... // Create ExecutorService.
Callable<Result> callable = new MyCallable(); // Create work to be done.
Future<Result> fut = executorService.submit(callable);
让一个线程反复从队列中提取()
,并通过调用
isDone()
检查每个
DelayedImpl
未来
是否已完成;如果没有,则取消该任务

new Thread(new Runnable() {
  public void run() {
    while (!Thread.interrupted) {
      DelayedImpl impl = queue.take(); // Perform blocking take.
      if (!impl.getFuture().isDone()) {
        impl.getFuture().cancel(true);
      }
    }
  }
}).start();
此方法的主要优点是,您可以为每个任务设置不同的最大执行时间,延迟队列将自动返回剩余执行时间最小的任务。

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;
    }
}
类DelayedImpl实现延迟{
私人未来任务;
private final long maxExecTimeMinutes=MAX_THREAD_LIFE_MINUTES;
private final long startInMillis=System.currentTimeMillis();
专用延迟MPL(未来任务){
this.task=任务;
}
公共长getDelay(时间单位){
返回单位.convert((startInMillis+maxExecTimeMinutes*60*1000)-System.currentTimeMillis(),TimeUnit.毫秒);
}
公共内部比较(延迟o){
Long thisDelay=getDelay(时间单位为毫秒);
Long thatDelay=o.getDelay(时间单位为毫秒);
返回thisDelay.compareTo(thatDelay);
}
公共未来任务{
返回任务;
}
}
Future.get(长超时,TimeUnit)抛出TimeoutException肯定会这样做吗?我假定在捕获此异常的过程中,您称之为future.cancel(true)…future.get(long,TimeUnit)将在指定的时间内阻止特定的future完成。但是,我添加的解决方案允许您使用单个线程检查所有正在进行的可调用项,而不是阻塞特定的可调用项。假设我提交了一个需要5分钟的Callable;在我的“检查”线程中,我调用future.get(5L,TimeUnit.MINUTES)。然后提交另一个可调用文件,最长执行时间为10秒。但是,在前一个阻塞调用返回之前,线程不会查看第二个可调用是否已经运行了>10秒。
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;
    }
}