`
Dapple
  • 浏览: 101692 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Concurrent包常用方法简介

阅读更多

1 Executor接口

留给开发者自己实现的接口,一般情况下不需要再去实现。它只有一个方法

void execute(Runnable command)

2 ExecutorService接口

它继承自Executor接口,但多了如下3个功能

  1. 终止任务。体现在这几个方法
    1. void shutdown()
      1. 线程池关闭,不接受新任务,即不能再执行submit(task),如果你硬要执行新任务则会抛异常。
      2. 还没运行完的任务继续运行完毕.
    2. List<Runnable> shutdownNow()
      1. 试图停止所有正在执行的活动任务,但不一定成功。
      2. 返回等待执行的任务列表。
  2. 任务提交者与任务的通信,就是Future对象的使用。Future有点类似 windows开发中的句柄概念,通过它可对任务进行监控并获取任务信息。有三种使用方式:
    1. <T> Future<T> submit(Callable<T> task)
    2. Future<?> submit(Runnable task) 
    3. <T> Future<T> submit(Runnable task, T result)
    1. 第一种方法提交的任务,当任务完成后,可以通过Future.get()获取任务的返回值.
    2. 第三种方法提交的任务,当任务完成后,可以通过Future.get()获取提交时传递的参数T result. 比如:
      Future<String> future = service.submit(task,"aaaa");
      String s = future.get();// s="aaaa";
    3. 有趣的是第二种方式,因为它的Future.get()得不到任何内容,它返回值是Null,那为什么不直接把ExecutorService的接口设计成如下这种形式呢
      void submit(Runnable task)

      这是因为Future除了get这种获取任务信息外,还可以控制任务,体现在 Future的这个方法上

      boolean cancel(boolean mayInterruptIfRunning)

      这个方法的JavaDoc解释的很清楚

      Attempts to cancel execution of this task. This attempt will
      fail if the task has already completed, already been
      cancelled, or could not be cancelled for some other reason. If
      successful, and this task has not started when cancel is
      called, this task should never run. If the task has already
      started, then the mayInterruptIfRunning parameter determines
      whether the thread executing this task should be interrupted
      in an attempt to stop the task.

      注意:如果任务没执行完,这3种方式的Future.get()都会阻塞。

  3. 终止任务后可以阻塞一会儿。由ExecutorService的下面这个方法完成
    boolean awaitTermination(long timeout,TimeUnit unit)

    比如

    service.shutdown();
    service.awaitTermination(20, TimeUnit.SECONDS);

    它的意思是,当service.shutdown()后,主线程阻塞,任务执行结束或者阻塞20秒以后,阻塞解除。

3 ScheduledExecutorService接口

它继承自ExecutorService接口。顾名思义,它主要用来定期执行任务或周期执行任务。它只有4个方法,都比较好理解。下面用最简单的例子来做个说明

scheduler.schedule(callable,10,SECONDS); //10秒后开始执行callable任务
scheduler.schedule(runnable,10,Seconds); //10秒后开始执行runnable任务
scheduler.scheduleAtFixedRate(runnable, 5, 10, SECONDS); //5秒后开始执行Runnable任务,然后每隔10秒执行一遍该任务.
scheduler.scheduleWithFixedDelay(runnable,5,10,SECONDS); //5秒后开始执行Runnable任务,然后任务执行完后再等10秒就执行一遍任务,即,每隔任务执行的时间+10秒再执行一遍任务。

这4个方法都返回ScheduledFuture对象.它继承自Future接口,用途和Future差不多。

在JDK之前,计划任务一般由java.until.Timer类来完成。但相比起 ScheduleExecutorService来说,Timer类的功能较为简单,比如下例

private final static long fONCE_PER_DAY = 1000*60*60*24;
Timer timer = new Timer();
timer.scheduleAtFixedRate(fetchMail, getTomorrowMorning4am(), fONCE_PER_DAY);
  1. Timer没有返对象(我总理解为一种句柄),不方便细粒度控制任务。
  2. Timer的任务类型比较单一,只有TimerTask一种。
  3. 没有类似scheduleWithFixedDelay的方法。
  4. 间隔时间的表示方法也不友好。
  5. 性能上也不如ScheduledExecutorService(通过线程池等方式进行了性能优化)出色。

4 Executors类

这个类是一个工厂类,用来生成不同特点的ExecutorService或 ScheduledExecutorService实例。这里主要介绍这些不同特点的实例不同在什么地方。

  1. 3类不同的ExecutorService实例.
    static ExecutorService newSingleThreadExecutor()

    启动一个线程负责任务顺序执行,顺序意味着先提交的任务先执行。其原理是:任务会被提交到一个队列里,启动的那个线程会从队里里取任务,然后执行,执行完,再从队列里取下一个任务,再执行。如果该线程执行一个任务失败,并导致线程结束,系统会创建一个新的线程去执行队里里后续的任务,不会因为前面的任务有异常导致后面无辜的任务无法执行。

    static ExecutorService newCachedThreadPool()

    启动N个线程处理N个任务。既然是多个线程运行,意味着任务不会顺序运行。一个任务完成后,该线程空闲60秒会被结束。新提交的任务会发现空闲线程,并使用它,如果没有空闲线程可用则创建新线程。其实,这就是一个动态线程池。适合于规模比较小、创建较频繁的任务。

    static ExecutorService newFixedThreadPool(int nThreads)

    动态线程池不限制线程的数量,在有些情况下我们不希望线程数量不可控,则可以使用拥有固定线程数目的线程池。运作原理是:任务被提交到一个队列里排队,线程池里的空闲线程会把队列里的任务提出来执行,每个线程执行完一个任务后,就去队列里抓另一个任务出来执行。如果一个线程由于失败而终止,系统会创建另一个线程执行后续任务。

  2. 带ThreadFactory参数生成的ExecutorService实例。以上3种实例创建工作线程时都是用的默认的线程工厂类来创建。也可以指定自己的线程工厂类来创建,以newSingleThreadExecutor(ThreadFactory threadFactory)为例:
    //你自己的实现
    class YourselfThreadFactory implements ThreadFactory {
        public Thread newThread(Runnable r) {
            Thread thread = new Thread(r);
            doXXX;
            return thread;
        }
    }
  3. newSingleThreadExecutor 与 newFixedThreadPool(1) 区别.

    JavaDoc上说:Unlike the otherwise equivalent newFixedThreadPool(1) the returned executor is guaranteed not to be reconfigurable to use additional threads.

    什么意思?不懂。为什么?不具体。具体一下就懂了。

    ((ThreadPoolExecutor)newFixedThreadPool(1)).setCorePoolSize(3);

    即newFixedThreadPool(1)可以后期修改线程数,不能保证线程只有一个。而newSingleThreadExecutor可以保证。

  4. static Callable<Object> callable(Runnable task)

    把Runnable任务转换成Callable任务.例子如下

    public static void test() throws Exception {
        Runnable task = new Runnable() {
                public void run() {
                    log("begin task");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                    }
                    log("end task");
                }
            };
        Callable c = Executors.callable(task);
        ExecutorService service = Executors.newCachedThreadPool();
        Future f = service.submit(c);
        System.out.println(f.get());//返回null
        log("end");
    }
            
    private static void log(String message) {
        System.out.println(new Date() + ": " + message);
    }
    
    public static void main(String args[]) throws Exception {
        test();
    }

5 结束

JDK1.5引入的concurrent包使多线程编写更加容易、代码更容易理解、可读性更好. 相关文章,请参考 http://hi.baidu.com/dapplehou/blog/item/0a4c65388143b72c96ddd814.html

author: Dapple Hou email: mmonkeyer@163.com

 

http://hi.baidu.com/dapplehou/blog/item/11ccbaa1c8a0789b461064e9.html

0
0
分享到:
评论
2 楼 jiashaoshan 2012-12-20  
jiashaoshan 写道
引用

1 楼 jiashaoshan 2012-12-20  
引用
死死死死死死

相关推荐

    Concurrent包的小例子

    Concurrent下的例子,涵盖了大部分常用类 例如BlockingQueue、CountDownLatch、CyclicBarrier、Exchanger、ExecuteService、lock、timeutil等

    JDK concurrent

    这些模式是解决并发问题的常用方法,通过学习可以提升代码的可维护性和性能。 "j-concur.zip" 文件可能包含了一些示例代码或者补充资料,用于演示和实践Java并发编程的技巧。这些示例通常会涵盖各种并发控制机制,...

    java5 并发包 (concurrent)思维导图

    Java 5并发包(`java.util.concurrent`,简称`Concurrent`包)是Java平台中用于多线程编程的重要组成部分,它提供了丰富的并发工具类,极大地简化了在多线程环境下的编程工作。这个包的设计目标是提高并发性能,减少...

    Java Concurrent Programming

    为了简化多线程编程,Java提供了一系列工具和API,如`java.util.Timer`和`java.util.concurrent`包,这些工具可以帮助开发者更高效地管理线程间的同步问题。 ##### 1.2 synchronized关键字 `synchronized`关键字是...

    java的concurrent用法详解

    ### Java的Concurrent包用法详解 #### 一、引言 在Java 1.5之前,为了实现多线程的并发操作,开发者通常需要手动编写复杂的代码来处理线程间的同步问题,如使用`synchronized`关键字、`wait()`与`notify()`方法等。...

    常用Java开发jar包三 java程序开发常用的jar包

    在并发编程领域,Java标准库提供了java.util.concurrent包,包含了许多高级并发工具,如ExecutorService、Future、Callable等。此外,Quasar是一个异步编程库,它引入了纤程(fibers)的概念,可以提高多线程应用的...

    一些常用的jar包

    5. **并发与线程**:`concurrent`包提供了高级并发工具,`lombok`简化了JavaBean的创建,自动处理getter、setter等。 6. **测试工具**:`junit`是单元测试的基石,`mockito`用于模拟对象,`selenium`支持自动化...

    Learning Concurrent Programming in Scala

    除了Scala本身提供的并发支持外,书中还会介绍一些常用的并发编程工具和框架,比如Akka框架,它是基于Actor模型的开源工具包,广泛应用于构建高度并发、分布式和容错的系统。 #### 六、并发性能优化技巧 本书还...

    java常用包 81个

    9. `java.concurrent`:并发编程包,提供了线程池、并发集合、同步工具类等,如 `ExecutorService`、`Future`、`Semaphore`、`CyclicBarrier`,帮助开发者更安全地进行多线程编程。 10. `java.text`:处理文本格式...

    java_jdk_api中文文档 部分常用类包

    虽然这个文档不全面,但涵盖了日常开发中常用的类型,对于理解和使用Java语言具有极大的帮助。 在Java JDK API中,我们可以找到以下主要的包和类: 1. **java.lang**:这是Java程序的基础包,包含了所有Java程序...

    常用的两个jar包

    本话题将重点介绍两个常用的`jar`包——`concurrent-1.3.2.jar`和`connector.jar`,以及它们所涉及的核心知识点。 `concurrent-1.3.2.jar`是Java并发编程领域的一个重要组件,它包含了Java并发库的一部分早期实现。...

    Concurrent.Programming.in.Java - Design.Principles.and.Patterns(Second.Edition)

    本书《Concurrent Programming in Java - Design Principles and Patterns (Second Edition)》深入探讨了在Java编程语言中进行并发编程的方法、设计理念及其实现技巧。它假设读者已经具备面向对象编程的经验,但对于...

    java常用jar包

    - `concurrent.jar`: 包含了Java并发处理的类库,如`java.util.concurrent`包下的工具类。 13. **图形用户界面JAR** - `swing.jar`: Java Swing库提供了丰富的组件,用于构建桌面应用程序的用户界面。 以上只是...

    java.util.concurrent 测试源文件

    Java.util.concurrent(JUC)是Java平台中的一个核心包,专门用于处理多线程并发问题。这个包包含了大量的工具类和接口,极大地简化了并发编程的复杂性,提高了程序的性能和可伸缩性。本测试源文件主要是针对JUC并发...

    java_util_concurrent_user_guide并发工具包详解

    Java并发工具包(java.util.concurrent)是Java编程中不可或缺的一部分,它为多线程环境提供了高效、安全且易用的工具。这个包包含了各种类和接口,帮助开发者编写高效的并发程序,避免了直接操作线程所带来的复杂性...

    常用jar包大全

    "常用jar包大全"这个资源集合提供了69个常用的JAR文件,旨在帮助开发者快速获取并使用这些常用的库,避免在项目开发中花费大量时间去寻找和集成。 1. **JAR文件的基础知识** - JAR文件是Java平台特有的归档格式,...

Global site tag (gtag.js) - Google Analytics