实现一个基于优先级的executor类
在java并发api的第一个版本中,你必须创建和运行应用程序中的所有线程。在java版本5中,随着执行者框架(executor framework)的出现,对于并发任务的执行,一个新的机制被引进。
使用执行者框架(executor framework),你只要实现你的任务并把它们提交给执行者。这个执行者负责执行你的任务的线程的创建和执行。
在内部,一个执行者使用一个阻塞队列来存储待处理任务。以任务到达执行者的顺序来存储。一个可能的替代就是使用一个优先级列队来存储新的任务。这样,如果一个高优先级的新任务到达执行者,它将比其他已经在等待一个线程来执行它们,且低优先级的任务先执行。
在这个指南中,你将学习如何实现一个执行者,它将使用优先级队列来存储你提交执行的任务。
准备工作
这个指南的例子使用eclipse ide实现。如果你使用eclipse或其他ide,如netbeans,打开它并创建一个新的java项目。
如何做…
按以下步骤来实现的这个例子:
1.创建一个myprioritytask类,它实现runnable接口和参数化为myprioritytask类的comparable接口。
<code>1</code>
<code>public</code> <code>class</code> <code>myprioritytask</code><code>implements</code> <code>runnable,</code>
<code>2</code>
<code>comparable<myprioritytask> {</code>
2.声明一个私有的、int类型的属性priority。
<code>private</code> <code>int</code> <code>priority;</code>
3.声明一个私有的、string类型的属性name。
<code>private</code> <code>string name;</code>
4.实现这个类的构造器,并初始化它的属性。
<code>public</code> <code>myprioritytask(string name,</code><code>int</code> <code>priority) {</code>
<code>this</code><code>.name=name;</code>
<code>3</code>
<code>this</code><code>.priority=priority;</code>
<code>4</code>
<code>}</code>
5.实现一个方法来返回priority属性的值。
<code>public</code> <code>int</code> <code>getpriority(){</code>
<code>return</code> <code>priority;</code>
6.实现声明在comparable接口中的compareto()方法。它接收一个myprioritytask对象作为参数,比较这两个对象(当前对象和参数对象)的优先级。让优先级高的任务先于优先级低的任务执行。
<code>01</code>
<code>@override</code>
<code>02</code>
<code>public</code> <code>int</code> <code>compareto(myprioritytask o) {</code>
<code>03</code>
<code>if</code> <code>(</code><code>this</code><code>.getpriority() < o.getpriority()) {</code>
<code>04</code>
<code>return</code> <code>1</code><code>;</code>
<code>05</code>
<code>06</code>
<code>if</code> <code>(</code><code>this</code><code>.getpriority() > o.getpriority()) {</code>
<code>07</code>
<code>return</code> <code>-</code><code>1</code><code>;</code>
<code>08</code>
<code>09</code>
<code>return</code> <code>0</code><code>;</code>
<code>10</code>
7.实现run()方法。令当前线程睡眠2秒。
<code>public</code> <code>void</code> <code>run() {</code>
<code>system.out.printf("myprioritytask: %s priority :</code>
<code>%d\n",name,priority);</code>
<code>try</code> <code>{</code>
<code>timeunit.seconds.sleep(</code><code>2</code><code>);</code>
<code>}</code><code>catch</code> <code>(interruptedexception e) {</code>
<code>e.printstacktrace();</code>
8.实现这个例子的主类,通过创建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>
9.创建一个threadpoolexecutor对象,名为executor。使用参数化为runnable接口的priorityblockingqueue作为执行者用来存储待处理任务的队列。
<code>threadpoolexecutor executor=</code><code>new</code> <code>threadpoolexecutor(</code><code>2</code><code>,</code><code>2</code><code>,</code><code>1</code><code>,timeu</code>
<code>nit.seconds,</code><code>new</code> <code>priorityblockingqueue<runnable>());</code>
10.提交4个使用循环计数器作为优先级的任务给执行者。使用execute()方法提交这些任务给执行者。
<code>for</code> <code>(</code><code>int</code> <code>i=</code><code>0</code><code>; i<</code><code>4</code><code>; i++){</code>
<code>myprioritytask task=</code><code>new</code> <code>myprioritytask (</code><code>"task "</code><code>+i,i);</code>
<code>executor.execute(task);</code>
11.令当前线程睡眠1秒。
<code>timeunit.seconds.sleep(</code><code>1</code><code>);</code>
<code>5</code>
12.提交4个额外的,使用循环计数器作为优先级的任务给执行者。使用execute()方法提交这些任务给执行者。
<code>for</code> <code>(</code><code>int</code> <code>i=</code><code>4</code><code>; i<</code><code>8</code><code>; i++) {</code>
13.使用shutdown()方法关闭这个执行者。
<code>executor.shutdown();</code>
14.使用awaittermination()方法等待这个执行者的结束。
<code>executor.awaittermination(</code><code>1</code><code>, timeunit.days);</code>
15.写入一条信息表明这个程序的结束。
<code>system.out.printf(</code><code>"main: end of the program.\n"</code><code>);</code>
它是如何工作的…
很容易将执行者转换成一个基于优先级的(执行者)。你只要传入一个参数化为runnable接口的priorityblockingqueue对象作为参数。但是,使用执行者时,你应该知道存储在优先级列队中的所有对象必须实现comparable接口。
你已经实现了myprioritytask类,(作为一个任务)它实现了runnable接口和comparable接口,它被存储在优先级队列中。这个类有一个priority属性,用来存储任务的优先级。如果一个任务的这个属性有更高的值,它将被更早的执行。compareto()方法决定任务在优先级列队中的顺序。在main类,你提交8个不同优先级的任务给执行者。你提交给执行者的第一个任务将第一个被执行。由于执行者闲置的,正在等待任务被执行,当第一个任务到达执行者时,执行者立即执行它们。你已经创建有2个执行线程的执行者,所以,前两个任务将第一个被执行。然后,剩下的任务将按它们的优先级来执行。
以下截图显示了示例的一次执行:

不止这些…
你可以使用任何实现blockingqueue接口(的队列)来配置执行者。delayqueue是一个有趣的实现。这个类被用来存储延迟激活(delayed activation)的元素。它提供只返回活动对象的方法。你可以使用这个类来实现自己版本的scheduledthreadpoolexecutor类。