ExecutorService中队列中的最长等待时间

时间:2016-09-07 14:38:12

标签: java multithreading

有没有办法在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();
                        }
                    }
                }
            });
        }
    }

2 个答案:

答案 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
}

希望这有帮助。