`

Java 5.0多线程编程 Executor

阅读更多
http://java.chinaitlab.com/line/397966_2.html
http://www.builder.com.cn/2007/0828/474645.shtml


*1: 定义了几个任务
*2: 初始了任务执行工具。任务的执行框架将会在后面解释。
*3: 执行任务,任务启动时返回了一个Future对象,如果想得到任务执行的结果或者是异常可对这个Future对象进行操作。Future所含的值必须跟Callable所含的值对映,比如说例子中Future对印Callable
*4: 任务1正常执行完毕,future1.get()会返回线程的值
*5: 任务2在进行一个死循环,调用future2.cancel(true)来中止此线程。传入的参数标明是否可打断线程,true表明可以打断。
*6: 任务3抛出异常,调用future3.get()时会引起异常的抛出。
运行Executor会有以下运行结果:
looping....

Task done. //*1

looping....

looping....//*2

looping....

looping....

looping....

looping....

Thread 2 terminated? :true //*3

//*4

java.util.concurrent.ExecutionException: java.lang.Exception: Callable terminated with Exception!

        at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:205)

        at java.util.concurrent.FutureTask.get(FutureTask.java:80)

        at concurrent.Executor.main(Executor.java:43)

        …….


*1: 任务1正常结束
*2: 任务2是个死循环,这是它的打印结果
*3: 指示任务2被取消
*4: 在执行future3.get()时得到任务3抛出的异常
3:新的任务执行架构
   在Java 5.0之前启动一个任务是通过调用Thread类的start()方法来实现的,任务的提于交和执行是同时进行的,如果你想对任务的执行进行调度或是控制同时执行的线程数量就需要额外编写代码来完成。5.0里提供了一个新的任务执行架构使你可以轻松地调度和控制任务的执行,并且可以建立一个类似数据库连接池的线程池来执行任务。这个架构主要有三个接口和其相应的具体类组成。这三个接口是Executor, ExecutorService和ScheduledExecutorService,让我们先用一个图来显示它们的关系:


  图的左侧是接口,图的右侧是这些接口的具体类。注意Executor是没有直接具体实现的。
Executor接口:
是用来执行Runnable任务的,它只定义一个方法:
execute(Runnable command):执行Ruannable类型的任务
ExecutorService接口:
ExecutorService继承了Executor的方法,并提供了执行Callable任务和中止任务执行的服务,其定义的方法主要有:
submit(task):可用来提交Callable或Runnable任务,并返回代表此任务的Future对象
invokeAll(collection of tasks):批处理任务集合,并返回一个代表这些任务的Future对象集合
shutdown():在完成已提交的任务后关闭服务,不再接受新任务
shutdownNow():停止所有正在执行的任务并关闭服务。
isTerminated():测试是否所有任务都执行完毕了。
isShutdown():测试是否该ExecutorService已被关闭
ScheduledExecutorService接口
在ExecutorService的基础上,ScheduledExecutorService提供了按时间安排执行任务的功能,它提供的方法主要有:
schedule(task, initDelay): 安排所提交的Callable或Runnable任务在initDelay指定的时间后执行。
scheduleAtFixedRate():安排所提交的Runnable任务按指定的间隔重复执行
scheduleWithFixedDelay():安排所提交的Runnable任务在每次执行完后,等待delay所指定的时间后重复执行。
代码:ScheduleExecutorService的例子
public class ScheduledExecutorServiceTest {

        public static void main(String[] args)

               throws InterruptedException, ExecutionException{

               //*1

                ScheduledExecutorService service = Executors.newScheduledThreadPool(2);

                //*2

                Runnable task1 = new Runnable() {

                     public void run() {

                        System.out.println("Task repeating.");

                     }

                };

                //*3

                final ScheduledFuture future1 =

                        service.scheduleAtFixedRate(task1, 0, 1, TimeUnit.SECONDS);

                //*4

                ScheduledFuture future2 = service.schedule(new Callable(){

                     public String call(){

                             future1.cancel(true);

                             return "task cancelled!";

                     }

                }, 5, TimeUnit.SECONDS);

                System.out.println(future2.get());

//*5

service.shutdown();

        }

}


   这个例子有两个任务,第一个任务每隔一秒打印一句“Task repeating”,第二个任务在5秒钟后取消第一个任务。
*1: 初始化一个ScheduledExecutorService对象,这个对象的线程池大小为2。
*2: 用内函数的方式定义了一个Runnable任务。
*3: 调用所定义的ScheduledExecutorService对象来执行任务,任务每秒执行一次。能重复执行的任务一定是Runnable类型。注意我们可以用TimeUnit来制定时间单位,这也是Java 5.0里新的特征,5.0以前的记时单位是微秒,现在可精确到奈秒。
*4: 调用ScheduledExecutorService对象来执行第二个任务,第二个任务所作的就是在5秒钟后取消第一个任务。
*5: 关闭服务。
Executors类
   虽然以上提到的接口有其实现的具体类,但为了方便Java 5.0建议使用Executors的工具类来得到Executor接口的具体对象,需要注意的是Executors是一个类,不是Executor的复数形式。Executors提供了以下一些static的方法:
callable(Runnable task): 将Runnable的任务转化成Callable的任务
newSingleThreadExecutor: 产生一个ExecutorService对象,这个对象只有一个线程可用来执行任务,若任务多于一个,任务将按先后顺序执行。
newCachedThreadPool(): 产生一个ExecutorService对象,这个对象带有一个线程池,线程池的大小会根据需要调整,线程执行完任务后返回线程池,供执行下一次任务使用。
newFixedThreadPool(int poolSize):产生一个ExecutorService对象,这个对象带有一个大小为poolSize的线程池,若任务数量大于poolSize,任务会被放在一个queue里顺序执行。
newSingleThreadScheduledExecutor:产生一个ScheduledExecutorService对象,这个对象的线程池大小为1,若任务多于一个,任务将按先后顺序执行。
newScheduledThreadPool(int poolSize): 产生一个ScheduledExecutorService对象,这个对象的线程池大小为poolSize,若任务数量大于poolSize,任务会在一个queue里等待执行
以下是得到和使用ExecutorService的例子:
代码:如何调用Executors来获得各种服务对象
//Single Threaded ExecutorService

     ExecutorService singleThreadeService = Executors.newSingleThreadExecutor();

//Cached ExecutorService

     ExecutorService cachedService = Executors.newCachedThreadPool();

//Fixed number of ExecutorService

     ExecutorService fixedService = Executors.newFixedThreadPool(3);

//Single ScheduledExecutorService

     ScheduledExecutorService singleScheduledService =

          Executors.newSingleThreadScheduledExecutor();

//Fixed number of ScheduledExecutorService

ScheduledExecutorService fixedScheduledService =

     Executors.newScheduledThreadPool(3);


4:Lockers和Condition接口
   在多线程编程里面一个重要的概念是锁定,如果一个资源是多个线程共享的,为了保证数据的完整性,在进行事务性操作时需要将共享资源锁定,这样可以保证在做事务性操作时只有一个线程能对资源进行操作,从而保证数据的完整性。在5.0以前,锁定的功能是由Synchronized关键字来实现的,这样做存在几个问题:
每次只能对一个对象进行锁定。若需要锁定多个对象,编程就比较麻烦,一不小心就会出现死锁现象。
如果线程因拿不到锁定而进入等待状况,是没有办法将其打断的
在Java 5.0里出现两种锁的工具可供使用,下图是这两个工具的接口及其实现:


分享到:
评论

相关推荐

    Java 5_0 多线程编程实践

    ### Java 5.0 多线程编程实践 在Java 5.0版本中,多线程编程得到了显著增强,特别是在引入了`java.util.concurrent`包之后,为开发者提供了更为丰富的API来处理并发问题。本篇文章将深入探讨如何在Java 5.0中有效地...

    Java多线程-JDK5.0新增线程创建方式

    通过以上两个新增的线程创建方式,我们可以看到Java 5.0版本在多线程编程方面的改进和增强。使用`Callable`接口和线程池不仅提高了线程管理的灵活性,还增强了程序的可扩展性和性能表现。在实际开发过程中,根据具体...

    java-wrox-Beginning Java 5.0 2005

    - **并发工具包**:包括了新的并发类,如`Executor`框架、`ConcurrentHashMap`等,使得编写多线程程序更加容易。 - **泛型集合**:提供了泛型化的集合类,提高了类型安全性。 - **正则表达式引擎**:支持更强大的...

    JavaAPI_5.0(中文版)

    11. **并发编程改进**:Java 5.0加强了并发编程的支持,引入了`java.util.concurrent`包,包括`Executor`框架、`Future`接口、`Callable`接口以及线程安全的数据结构如`ConcurrentHashMap`。 12. **死锁检测**:JDK...

    JavaSE_J2SE_5.0_API_中文文档_html格式

    8. **并发编程改进**:Java 5.0对并发编程进行了大量改进,引入了`java.util.concurrent`包,包含线程池、Future、Executor框架等,大大简化了多线程编程。 9. **枚举类的常量工厂方法**:除了传统的枚举常量声明...

    《Java5.0 Tiger》书籍

    10. **并发API改进**:Java 5.0引入了`java.util.concurrent`包,提供了如Executor、Future、Callable等新接口和类,简化了多线程编程,提高了并发性能。 这本书的源码提供了实例,可以帮助读者更好地理解和应用...

    Java并发编程实践(英文非扫描版-带书签目录)

    书籍中涉及的内容广泛,涵盖了从基础概念到复杂场景下的并发问题解决方法,是多线程编程人员的重要参考资料。 书中特别强调了摩尔定律(Moore’s Law)和安达尔定律(Amdahl’s Law)对并发编程的影响。摩尔定律...

    java并发编程从入门到精通

    例如,生产者-消费者模式是多线程编程中经常使用的模式,它通过使用阻塞队列(BlockingQueue)来协调生产者和消费者之间的操作。还有诸如Future模式、读写模式等,这些模式不仅能够解决特定问题,还可以提高代码的...

    java 并发编程实践 英文版 English

    Java提供了丰富的API来支持多线程编程,包括`Thread`类、`Runnable`接口、`Executor`框架等,使得开发者能够构建高效、响应迅速的应用程序。 #### 2. 同步与锁 为了确保线程安全,避免数据竞争和死锁等问题,Java...

    [Java并发编程实践].(Java.Concurrency.in.Practice).Brian.Goetz.英文原版.pdf

    本书深入浅出地介绍了Java 5.0及之后版本中新增加的并发特性,并对并发编程进行了全面而详尽的讲解。自发布以来,这本书因其内容的专业性和实用性受到了广泛的赞誉。 #### 重要性与背景 随着计算机硬件的发展,多核...

    良葛格Java JDK 5.0学习笔记.rar

    这些特性为编写高效的多线程程序提供了便利。 总的来说,《良葛格Java JDK 5.0学习笔记》包含了Java编程的核心知识和实践技巧,对于任何希望深入了解Java技术的人来说,都是一份宝贵的资料。通过系统学习这份笔记,...

    Java并发编程实践-电子书

    本书全面覆盖了Java 5.0引入的并发库,这对于理解和掌握Java多线程编程至关重要。 在Java中,并发编程是解决多处理器或多核心环境下性能问题的关键技术。Java 5.0通过引入并发工具类和改进的线程模型,大大简化了...

    J2SERuntimeEnvironment5.0开发者版

    J2SE 5.0引入了java.util.concurrent包,包含了丰富的线程安全的数据结构和同步工具类,如Executor框架、Semaphore、CyclicBarrier等,这些工具极大地简化了多线程编程。 8. **死锁检测(Deadlock Detection)** ...

    Java并发编程实践

    《Java并发编程实践》一书正是为了解决开发者在多线程编程中遇到的问题而编写的。本书由Java并发模型的设计者之一Brian Goetz及他的团队撰写,他们也是Java 5.0和Java 6中的并发特性的主要贡献者。 #### 二、并发...

    [Java并发编程实践].(Java.Concurrency.in.Practice).Brian.Goetz.文字版

    本书面向那些希望在Java编程领域达到更高层次的专业人士,尤其是那些希望掌握多线程编程技巧、解决复杂并发问题的开发者。书中不仅详细介绍了Java 5.0和Java 6中新增加的并发特性,还提供了关于并发编程的一般性指导...

    JAVA大学教程(第五版)[16]

    通过以上章节内容的学习,我们可以了解到Java多线程编程的基础知识,包括并发的概念、线程的生命周期、优先级调度机制以及如何在J2SE 5.0环境中创建和执行线程。这些知识对于开发高性能、高并发的应用程序至关重要。

    Java虚拟机1.5

    10. **并发改进**:Java 5引入了新的并发工具类,如`java.util.concurrent`包,包含`Executor`框架、`Semaphore`、`CyclicBarrier`等,提高了多线程编程的效率和可靠性。 11. **NIO.2**:虽然Java 5没有完全引入NIO...

Global site tag (gtag.js) - Google Analytics