执行者控制被拒绝的任务
当你想要结束执行者的执行,你使用shutdown()方法来表明它的结束。执行者等待正在运行或等待它的执行的任务的结束,然后结束它们的执行。
如果你在shutdown()方法和执行者结束之间,提交任务给执行者,这个任务将被拒绝,因为执行者不再接收新的任务。threadpoolexecutor类提供一种机制,在调用shutdown()后,不接受新的任务。
在这个指南中,你将学习如何通过实现rejectedexecutionhandler,在执行者中管理拒绝任务。
准备工作…
这个指南的例子使用eclipse ide实现。如果你使用eclipse或其他ide,如netbeans,打开它并创建一个新的java项目。
如何做…
按以下步骤来实现的这个例子:
1.创建rejectedtaskcontroller类,实现rejectedexecutionhandler接口。实现这个接口的rejectedexecution()方法。写入被拒绝任务的名称和执行者的名称与状态到控制台。
<code>1</code>
<code>public</code> <code>class</code> <code>rejectedtaskcontroller </code><code>implements</code>
<code>2</code>
<code>rejectedexecutionhandler {</code>
<code>3</code>
<code>@override</code>
<code>4</code>
<code>public</code> <code>void</code> <code>rejectedexecution(runnable r, threadpoolexecutor executor) {</code>
<code>5</code>
<code>system.out.printf(</code><code>"rejectedtaskcontroller: the task %s has been rejected\n"</code><code>,r.tostring());</code>
<code>6</code>
<code>system.out.printf(</code><code>"rejectedtaskcontroller: %s\n"</code><code>,executor.tostring());</code>
<code>7</code>
<code>system.out.printf(</code><code>"rejectedtaskcontroller: terminating:%s\n"</code><code>,executor.isterminating());</code>
<code>8</code>
<code>system.out.printf(</code><code>"rejectedtakscontroller: terminated:%s\n"</code><code>,executor.isterminated());</code>
<code>9</code>
<code>}</code>
2.实现task类,实现runnable接口。
<code>public</code> <code>class</code> <code>task </code><code>implements</code> <code>runnable{</code>
3.声明私有的、string类型的属性name, 用来存储任务的名称。
<code>private</code> <code>string name;</code>
4.实现这个类的构造器,初始化这个类的属性。
<code>public</code> <code>task(string name){</code>
<code>this</code><code>.name=name;</code>
5.实现run()方法,写入信息到控制台,表明这个方法开始执行。
<code>public</code> <code>void</code> <code>run() {</code>
<code>system.out.println(</code><code>"task "</code><code>+name+</code><code>": starting"</code><code>);</code>
6.等待一段随机时间。
<code>try</code> <code>{</code>
<code>long</code> <code>duration=(</code><code>long</code><code>)(math.random()*</code><code>10</code><code>);</code>
<code>system.out.printf(</code><code>"task %s: reportgenerator: generating a report during %d seconds\n"</code><code>,name,duration);</code>
<code>timeunit.seconds.sleep(duration);</code>
<code>} </code><code>catch</code> <code>(interruptedexception e) {</code>
<code>e.printstacktrace();</code>
7.写入信息到控制台,表明方法的结束。
<code>system.out.printf(</code><code>"task %s: ending\n"</code><code>,name);</code>
8.重写tostring()方法,返回任务的名称。
<code>public</code> <code>string tostring() {</code>
<code>return</code> <code>name;</code>
9.实现这个示例的主类,通过创建main类,并实现main()方法。
<code>public</code> <code>class</code> <code>main {</code>
<code>public</code> <code>static</code> <code>void</code> <code>main(string[] args) {</code>
10.创建一个rejectedtaskcontroller对象,管理拒绝的任务。
<code>rejectectaskcontroller controller=</code><code>new</code> <code>rejectectaskcontroller();</code>
11.使用executors类的newcachedthreadpool()方法,创建threadpoolexecutor。
<code>threadpoolexecutor executor=(threadpoolexecutor) executors.newcachedthreadpool();</code>
12.建立执行者的拒绝任务控制器。
<code>executor.setrejectedexecutionhandler(controller);</code>
13.创建任务并提交它们给执行者。
<code>system.out.printf(</code><code>"main: starting.\n"</code><code>);</code>
<code>for</code> <code>(</code><code>int</code> <code>i=</code><code>0</code><code>; i<</code><code>3</code><code>; i++) {</code>
<code>task task=</code><code>new</code> <code>task(</code><code>"task"</code><code>+i);</code>
<code>executor.submit(task);</code>
14.使用shutdown()方法,关闭执行者。
<code>system.out.printf(</code><code>"main: shutting down the executor.\n"</code><code>);</code>
<code>executor.shutdown();</code>
15.创建其他任务并提交给执行者。
<code>system.out.printf(</code><code>"main: sending another task.\n"</code><code>);</code>
<code>task task=</code><code>new</code> <code>task(</code><code>"rejectedtask"</code><code>);</code>
16.写入信息到控制台,表明程序结束。
<code>system.out.println(</code><code>"main: end"</code><code>);</code>
<code>system.out.printf(</code><code>"main: end.\n"</code><code>);</code>
这是如何工作的…
以下截图显示示例的执行结果:

你可以看出当执行者关闭时,任务被拒绝提交。rejectectaskcontroller将有关于任务和执行者的信息写入到控制台。
为了管理执行者控制拒绝任务,你应该实现rejectedexecutionhandler接口。该接口有带有两个参数的方法rejectedexecution():
runnable对象,存储被拒绝的任务
executor对象,存储拒绝任务的执行者
每个被执行者拒绝的任务都会调用这个方法。你必须使用executor类的setrejectedexecutionhandler()方法设置拒绝任务的处理器。
不止这些…
当执行者接收任务时,会检查shutdown()是否已经被调用了。如果被调用了,它拒绝这个任务。首先,它查找 setrejectedexecutionhandler()设置的处理器。如果有一个(处理器),它调用那个类的 rejectedexecution()方法,否则,它将抛rejectedexecutionexeption异常。这是一个运行时异常,所以你不需要 用catch语句来控制它。
参见
在第4章,线程执行者中的创建一个线程执行者指南