有没有办法将任务放回执行程序队列中

Cra*_*lus 7 java concurrency multithreading executorservice executors

我有一系列Runnable要执行的任务(即s)Executor.
每个任务都要求某个条件有效才能继续.我很想知道是否有办法以某种方式配置Executor在队列末尾移动任务,并在条件有效且任务能够执行和完成时尝试执行它们.
所以行为是这样的:

  1. Thread-1从队列中获取任务run并被调用
  2. 内部run条件尚未生效
  3. 任务停止并将Thread-1任务放在队列的末尾,并执行下一个任务
  4. 稍后Thread-X(来自线程池)从队列条件再次选择任务是有效的并且正在执行任务

did*_*erc 3

首先创建执行器。

你有几种可能性。

如果我假设您的任务实现一个简单的接口来查询其状态(类似于带有“NeedReschedule”或“Completed”的枚举),那么Runnable为您的任务实现一个包装器(实现),它将任务和执行器作为实例化参数。该包装器将运行它所绑定的任务,然后检查其状态,并在必要时在终止之前在执行器中重新安排其自身的副本。

或者,您可以使用执行机制向包装器发出信号:必须重新安排任务。这个解决方案更简单,因为它不需要为您的任务提供特定的接口,因此Runnable可以毫无问题地将其简单地放入系统中。然而,异常会导致更多的计算时间(对象构造、堆栈跟踪等)。

这是使用异常信号机制的包装器的可能实现。您需要实现RescheduleException扩展类Throwable,它可以由包装的可运行对象触发(在此设置中的任务不需要更具体的接口)。您还可以使用另一个答案中建议的简单方法RuntimeException,但您必须测试消息字符串才能知道这是否是您正在等待的异常。

 public class TaskWrapper implements Runnable {

    private final ExecutorService executor;
    private final Runnable task;       

    public TaskWrapper(ExecutorService e, Runnable t){
         executor = e;
         task = t;
    }

@Override
public void run() {

    try {
               task.run();
    } 
    catch (RescheduleException e) {
        executor.execute(this);
    }
}
Run Code Online (Sandbox Code Playgroud)

这是一个非常简单的应用程序,随机启动 200 个打包任务,要求重新安排时间。

class Task implements Runnable {

  @Override
  public void run(){
     if (Maths.random() > 0.5)
      throw new RescheduleException();
   }     
}


public class Main {

public static void main(String[] args){

    ExecutorService executor = Executors.newFixedThreadPool(10);

    int i = 200;
            while(i--)
       executor.execute(new TaskWrapper(executor, new Task());
}
}
Run Code Online (Sandbox Code Playgroud)

您还可以有一个专用线程来监视其他线程结果(使用消息队列)并在必要时重新安排,但与其他解决方案相比,您会丢失一个线程。