java - ExecutorService超时而不阻塞主线程

标签 java multithreading concurrency

我想在有时间限制的后台执行一些工作。问题是,我不想阻塞主线程。

天真的实现是有两个执行器服务。一个负责安排/超时,第二个负责完成工作。

final ExecutorService backgroundExecutor = Executors.newSingleThreadExecutor();
final ExecutorService workerExecutor = Executors.newCachedThreadExecutor();


backgroundExecutor.execute(new Runnable() {
    public void run() {
        Future future = workerExecutor.submit(new Runnable() {
            public void run() {
                // do work
            }
        });
        try {
            future.get(120 * 1000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            logger.error("InterruptedException while notifyTransactionStateChangeListeners()", e);
            future.cancel(true);
        } catch (ExecutionException e) {
            logger.error("ExecutionException", e);
        } catch (TimeoutException e) {
            logger.error("TimeoutException", e);
            future.cancel(true);
        }
    }
});

还有其他解决办法吗?

最佳答案

您不需要 ExecutorService 只是像那样运行一个线程一次。您可以创建一个 FutureTask,它可以在没有开销的情况下为您提供相同的好处。

FutureTask<T> future = new FutureTask<T>(callable);
Thread thread = new Thread(future);
thread.start();
try {
    future.get(120 * 1000, TimeUnit.MILLISECONDS);
} ...

上述代码段中的可调用项将是您的任务。 如果你有一个 Runnable(就像你在上面的代码块中所做的那样),你可以通过以下方式将它变成一个 Callable:

Callable callable = Executors.callable(runnable, null);

因此,总而言之,您的代码可以更改为:

backgroundExecutor.execute(new Runnable() {
    public void run() {

        Runnable myRunnable = new Runnable() {
            public void run() {
                // do work
            }
        } 

        Callable callable = Executors.callable(myRunnable, null);

        FutureTask<T> future = new FutureTask<T>(callable);
        Thread thread = new Thread(future);
        thread.start();

        try {
            future.get(120 * 1000, TimeUnit.MILLISECONDS);
        } catch (InterruptedException e) {
            logger.error("InterruptedException while notifyTransactionStateChangeListeners()", e);
            future.cancel(true);
        } catch (ExecutionException e) {
            logger.error("ExecutionException", e);
        } catch (TimeoutException e) {
            logger.error("TimeoutException", e);
            future.cancel(true);
        } 
    }
});

您不需要 finally 来关闭执行程序。尽管您可能仍希望使用 finally 来清理任何其他资源。

关于java - ExecutorService超时而不阻塞主线程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10333895/

相关文章:

java - Libgdx 滚动 TiledMaps

java - 如何在 java 脚本中创建 ScriptableObject 对象......?

java - 赋值和创建字符串实例有什么区别?

java - 如何正确使用信号量

java - java线程数>内核数和垃圾回收

c++ - 在 C++ 中创建线程池的最简单方法?

java - 发送完所有未决消息后关闭套接字

java - 在线程中创建然后使用 JDBC 语句的最佳设计

go - 就绪时将值发送到 channel 并读取输出

java - Java:两个线程同时对给定范围内的数字求和:当仅连接一个线程时,第二个线程的总和太大