ExecutorService的超时,而不阻止主线程 [英] Timeout for ExecutorService without blocking the main thread

查看:383
本文介绍了ExecutorService的超时,而不阻止主线程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在时间限制的背景下执行一些工作。事情是,我不想阻塞主线程。

I would like to execute some work in a background with a time limit. The thing is, I don't want to block the main thread.

Naive实现是有两个执行器服务。一个用于调度/超时,第二个将负责完成工作。

Naive implementation is to have two executor services. One for scheduling/timeout and the second one will be responsible for getting work done.

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只是运行一个单线程一次。

You don't need an ExecutorService just to run a single thread one time like that. You can create a FutureTask instead which gives you the same benefits without the overhead.

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

上述代码段中的callable将是你的任务。
如果你有一个Runnable(和你上面的代码块一样),你可以通过:

The callable in the above snippet would be your task. If you have a Runnable (as you do in your above code block) you can turn it into a Callable via:

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

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

So, to summarize, your code could change to:

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);
        } 
    }
});

你不需要最后关闭执行器。虽然您可能仍需要最后清理任何其他资源。

You don't need a finally to shut down the executor. Though you might still want a finally to clean up any other resources.

这篇关于ExecutorService的超时,而不阻止主线程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆