天天看点

Java线程池 ExecutorService

executorservice是java中对线程池定义的一个接口,它<code>java.util.concurrent</code>包中,在这个接口中定义了和后台任务执行相关的方法:

Java线程池 ExecutorService

java api对executorservice接口的实现有两个,所以这两个即是java线程池具体实现类(详细了解这两个实现类,点击这里):

除此之外,executorservice还继承了<code>executor</code>接口(注意区分executor接口和executors工厂类),这个接口只有一个<code>execute()</code>方法,最后我们看一下整个继承树:

Java线程池 ExecutorService

创建一个什么样的executorservice的实例(即线程池)需要g根据具体应用场景而定,不过java给我们提供了一个<code>executors工厂类</code>,它可以帮助我们很方便的创建各种类型executorservice线程池,executors一共可以创建下面这四类线程池:

备注:executors只是一个工厂类,它所有的方法返回的都是<code>threadpoolexecutor</code>、<code>scheduledthreadpoolexecutor</code>这两个类的实例。

executorservice有如下几个执行方法:

这个方法接收一个runnable实例,并且异步的执行,请看下面的实例:

这个方法有个问题,就是没有办法获知task的执行结果。如果我们想获得task的执行结果,我们可以传入一个callable的实例(下面会介绍)。

<code>submit(runnable)</code>和<code>execute(runnable)</code>区别是前者可以返回一个future对象,通过返回的future对象,我们可以检查提交的任务是否执行完毕,请看下面执行的例子:

如果任务执行完成,<code>future.get()</code>方法会返回一个null。注意,future.get()方法会产生阻塞。

<code>submit(callable)</code>和<code>submit(runnable)</code>类似,也会返回一个future对象,但是除此之外,submit(callable)接收的是一个callable的实现,callable接口中的<code>call()</code>方法有一个返回值,可以返回任务的执行结果,而runnable接口中的<code>run()</code>方法是<code>void</code>的,没有返回值。请看下面实例:

如果任务执行完成,future.get()方法会返回callable任务的执行结果。注意,future.get()方法会产生阻塞。

<code>invokeany(...)</code>方法接收的是一个callable的集合,执行这个方法不会返回future,但是会返回所有callable任务中其中一个任务的执行结果。这个方法也无法保证返回的是哪个任务的执行结果,反正是其中的某一个。请看下面实例:

大家可以尝试执行上面代码,每次执行都会返回一个结果,并且返回的结果是变化的,可能会返回“task2”也可是“task1”或者其它。

<code>invokeall(...)</code>与 <code>invokeany(...)</code>类似也是接收一个callable集合,但是前者执行之后会返回一个future的list,其中对应着每个callable任务执行后的future对象。情况下面这个实例:

当我们使用完成executorservice之后应该关闭它,否则它里面的线程会一直处于运行状态。

举个例子,如果的应用程序是通过main()方法启动的,在这个main()退出之后,如果应用程序中的executorservice没有关闭,这个应用将一直运行。之所以会出现这种情况,是因为executorservice中运行的线程会阻止jvm关闭。

如果要关闭executorservice中执行的线程,我们可以调用<code>executorservice.shutdown()</code>方法。在调用shutdown()方法之后,executorservice不会立即关闭,但是它不再接收新的任务,直到当前所有线程执行完成才会关闭,所有在shutdown()执行之前提交的任务都会被执行。

如果我们想立即关闭executorservice,我们可以调用<code>executorservice.shutdownnow()</code>方法。这个动作将跳过所有正在执行的任务和被提交还没有执行的任务。但是它并不对正在执行的任务做任何保证,有可能它们都会停止,也有可能执行完成。

关于java线程池类threadpoolexecutor、scheduledthreadpoolexecutor及executors工厂类更详细介绍,点击这里