定制并发类(三)实现一个基于优先级的Executor类

声明:本文是《 Java 7 Concurrency Cookbook》的第七章,作者: Javier Fernández González     译者:许巧辉

实现一个基于优先级的Executor类

在Java并发API的第一个版本中,你必须创建和运行应用程序中的所有线程。在Java版本5中,随着执行者框架(Executor framework)的出现,对于并发任务的执行,一个新的机制被引进。

使用执行者框架(Executor framework),你只要实现你的任务并把它们提交给执行者。这个执行者负责执行你的任务的线程的创建和执行。

在内部,一个执行者使用一个阻塞队列来存储待处理任务。以任务到达执行者的顺序来存储。一个可能的替代就是使用一个优先级列队来存储新的任务。这样,如果一个高优先级的新任务到达执行者,它将比其他已经在等待一个线程来执行它们,且低优先级的任务先执行。

在这个指南中,你将学习如何实现一个执行者,它将使用优先级队列来存储你提交执行的任务。

准备工作

这个指南的例子使用Eclipse IDE实现。如果你使用Eclipse或其他IDE,如NetBeans,打开它并创建一个新的Java项目。

如何做…

按以下步骤来实现的这个例子:

1.创建一个MyPriorityTask类,它实现Runnable接口和参数化为MyPriorityTask类的Comparable接口。

1 public class MyPriorityTask implements Runnable,
2 Comparable<MyPriorityTask> {

2.声明一个私有的、int类型的属性priority。

1 private int priority;

3.声明一个私有的、String类型的属性name。

1 private String name;

4.实现这个类的构造器,并初始化它的属性。

1 public MyPriorityTask(String name, int priority) {
2 this.name=name;
3 this.priority=priority;
4 }

5.实现一个方法来返回priority属性的值。

1 public int getPriority(){
2 return priority;
3 }

6.实现声明在Comparable接口中的compareTo()方法。它接收一个MyPriorityTask对象作为参数,比较这两个对象(当前对象和参数对象)的优先级。让优先级高的任务先于优先级低的任务执行。

01 @Override
02 public int compareTo(MyPriorityTask o) {
03 if (this.getPriority() < o.getPriority()) {
04 return 1;
05 }
06 if (this.getPriority() > o.getPriority()) {
07 return -1;
08 }
09 return 0;
10 }

7.实现run()方法。令当前线程睡眠2秒。

01 @Override
02 public void run() {
03 System.out.printf("MyPriorityTask: %s Priority :
04 %d\n",name,priority);
05 try {
06 TimeUnit.SECONDS.sleep(2);
07 } catch (InterruptedException e) {
08 e.printStackTrace();
09 }
10 }

8.实现这个例子的主类,通过创建Main类,并实现main()方法。

1 public class Main {
2 public static void main(String[] args) {

9.创建一个ThreadPoolExecutor对象,名为executor。使用参数化为Runnable接口的PriorityBlockingQueue作为执行者用来存储待处理任务的队列。

1 ThreadPoolExecutor executor=new ThreadPoolExecutor(2,2,1,TimeU
2 nit.SECONDS,new PriorityBlockingQueue<Runnable>());

10.提交4个使用循环计数器作为优先级的任务给执行者。使用execute()方法提交这些任务给执行者。

1 for (int i=0; i<4; i++){
2 MyPriorityTask task=new MyPriorityTask ("Task "+i,i);
3 executor.execute(task);
4 }

11.令当前线程睡眠1秒。

1 try {
2 TimeUnit.SECONDS.sleep(1);
3 } catch (InterruptedException e) {
4 e.printStackTrace();
5 }

12.提交4个额外的,使用循环计数器作为优先级的任务给执行者。使用execute()方法提交这些任务给执行者。

1 for (int i=4; i<8; i++) {
2 MyPriorityTask task=new MyPriorityTask ("Task "+i,i);
3 executor.execute(task);
4 }

13.使用shutdown()方法关闭这个执行者。

1 executor.shutdown();

14.使用awaitTermination()方法等待这个执行者的结束。

1 try {
2 executor.awaitTermination(1, TimeUnit.DAYS);
3 } catch (InterruptedException e) {
4 e.printStackTrace();
5 }

15.写入一条信息表明这个程序的结束。

1 System.out.printf("Main: End of the program.\n");

它是如何工作的…

很容易将执行者转换成一个基于优先级的(执行者)。你只要传入一个参数化为Runnable接口的PriorityBlockingQueue对象作为参数。但是,使用执行者时,你应该知道存储在优先级列队中的所有对象必须实现Comparable接口。

你已经实现了MyPriorityTask类,(作为一个任务)它实现了Runnable接口和Comparable接口,它被存储在优先级队列中。这个类有一个Priority属性,用来存储任务的优先级。如果一个任务的这个属性有更高的值,它将被更早的执行。compareTo()方法决定任务在优先级列队中的顺序。在Main类,你提交8个不同优先级的任务给执行者。你提交给执行者的第一个任务将第一个被执行。由于执行者闲置的,正在等待任务被执行,当第一个任务到达执行者时,执行者立即执行它们。你已经创建有2个执行线程的执行者,所以,前两个任务将第一个被执行。然后,剩下的任务将按它们的优先级来执行。

以下截图显示了示例的一次执行:

不止这些…

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

时间: 2024-08-19 00:10:48

定制并发类(三)实现一个基于优先级的Executor类的相关文章

定制并发类(十)实现一个基于优先级的传输队列

声明:本文是< Java 7 Concurrency Cookbook>的第七章, 作者: Javier Fernández González 译者:郑玉婷 实现一个基于优先级的传输队列 Java 7 API 提供几种与并发应用相关的数据类型.从这里面,我们想来重点介绍以下2种数据类型: LinkedTransferQueue:这个数据类型支持那些有生产者和消费者结构的程序. 在那些应用,你有一个或者多个数据生产者,一个或多个数据消费者和一个被生产者和消费者共享的数据类型.生产者把数据放入数据

发布一个基于javascript的动画类 Fx.js_javascript技巧

复制代码 代码如下: var example = new Fx(element,//元素 { form:{ //动画前的样式 //color:"#00f", }, to:{ //目标样式 color:"#00f", "background-color":"#5f5", opacity:0.9, }, //线性方法 transition:Transition.elasticInOut, //动画时间 duration:5000,

定制并发类(一)引言

声明:本文是< Java 7 Concurrency Cookbook>的第七章,作者: Javier Fernández González 译者:许巧辉 在这个文章中,我们将包含: 定制ThreadPoolExecutor类 实现一个基于优先级的Executor类 实现ThreadFactory接口生成自定义的线程 在一个Executor对象中使用我们的ThreadFactory 定制任务运行在一个计划的线程池中 实现ThreadFactory接口生成自定义的线程给Fork/Join框架 定

定制并发类(五)在一个Executor对象中使用我们的ThreadFactory

声明:本文是< Java 7 Concurrency Cookbook>的第七章,作者: Javier Fernández González     译者:许巧辉 在一个Executor对象中使用我们的ThreadFactory 在前面的指南中,实现ThreadFactory接口生成自定义线程,我们引进了工厂模式和提供如何实现一个实现ThreadFactory接口的线程的工厂例子. 执行者框架(Executor framework)是一种机制,它允许你将线程的创建与执行分离.它是基于Execu

PHP基于单例模式编写PDO类的方法_php技巧

一.单例模式简介 简单的说,一个对象(在学习设计模式之前,需要比较了解面向对象思想)只负责一个特定的任务: 二.为什么要使用PHP单例模式?      1.php的应用主要在于数据库应用, 所以一个应用中会存在大量的数据库操作, 使用单例模式, 则可以避免大量的new 操作消耗的资源.      2.如果系统中需要有一个类来全局控制某些配置信息, 那么使用单例模式可以很方便的实现. 这个可以参看ZF的FrontController部分.      3.在一次页面请求中, 便于进行调试, 因为所有

操作系统-基于优先级的时间片轮转调度算法

问题描述 基于优先级的时间片轮转调度算法 求一个基于优先级的时间片轮转调度算法.实在是不太会做了,没思路.要求java 要求: (1)设系统中有n个进程,每个进程PCB格式如下: 进程ID: 进程名称:p1,..., pn: 进程状态:1-运行,2-就绪,3-等待,0-完成: 进程类型:0-系统进程,1-用户进程: 请求资源时刻: 需要的CPU时间: 已运行时间: 优先级:数字小的优先级高: 指向下一进程的指针. (2)在调度程序运行之前,输入进程名称.所需CPU时间等. (3)设计4个队列,完

定制并发类(六)自定义在计划的线程池内运行的任务

声明:本文是< Java 7 Concurrency Cookbook>的第七章, 作者: Javier Fernández González 译者:郑玉婷 自定义在计划的线程池内运行的任务 计划的线程池是 Executor 框架的基本线程池的扩展,允许你定制一个计划来执行一段时间后需要被执行的任务. 它通过 ScheduledThreadPoolExecutor 类来实现,并允许运行以下这两种任务: Delayed 任务:这种任务在一段时间后仅执行一次. Periodic 任务:这种任务在延

定制并发类(七)实现ThreadFactory接口生成自定义的线程给Fork/Join框架

声明:本文是< Java 7 Concurrency Cookbook>的第七章,作者: Javier Fernández González     译者:许巧辉 实现ThreadFactory接口生成自定义的线程给Fork/Join框架 Fork/Join框架是Java7中最有趣的特征之一.它是Executor和ExecutorService接口的一个实现,允许你执行Callable和Runnable任务而不用管理这些执行线程. 这个执行者面向执行能被拆分成更小部分的任务.主要组件如下: 一

Dungeon Crawl Stone Soup一个基于Dungeon Crawl的rogue类游戏

这是一个基于Dungeon Crawl的rogue类游戏,它不同于nethack,故事很简单,也没有那么多剧情类的对白,这里主要就是探索.拥有在线服务器. Troll俗称巨魔+Berserker俗称狂战士,最好选使用武器而不是双手带钩.使用狂热的技能即使对手很强也不会输--能战胜所有强敌,杀死敌人食其肉.代价是把握好战斗时间,一旦累了而敌人没死,通常Game Over--需要相当长时间回复到正常速度,因此对付一堆敌人时要算准后事.少数地方,如在深渊精灵大圣堂灭其全族比较困难,其他多数敌人能比较简