Concurrent包常用方法简介
1 Executor接口
留给开发者自己实现的接口,一般情况下不需要再去实现。它只有一个方法
void execute(Runnable command)
2 ExecutorService接口
它继承自Executor接口,但多了如下3个功能
- 终止任务。体现在这几个方法
- void shutdown()
- 线程池关闭,不接受新任务,即不能再执行submit(task),如果你硬要执行新任务则会抛异常。
- 还没运行完的任务继续运行完毕.
- List<Runnable> shutdownNow()
- 试图停止所有正在执行的活动任务,但不一定成功。
- 返回等待执行的任务列表。
- void shutdown()
- 任务提交者与任务的通信,就是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)
- 第一种方法提交的任务,当任务完成后,可以通过Future.get()获取任务的返回值.
- 第三种方法提交的任务,当任务完成后,可以通过Future.get()获取提交时传递的参数T result. 比如:
Future<String> future = service.submit(task,"aaaa"); String s = future.get();// s="aaaa";
- 有趣的是第二种方式,因为它的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()都会阻塞。
- 终止任务后可以阻塞一会儿。由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);
- Timer没有返对象(我总理解为一种句柄),不方便细粒度控制任务。
- Timer的任务类型比较单一,只有TimerTask一种。
- 没有类似scheduleWithFixedDelay的方法。
- 间隔时间的表示方法也不友好。
- 性能上也不如ScheduledExecutorService(通过线程池等方式进行了性能优化)出色。
4 Executors类
这个类是一个工厂类,用来生成不同特点的ExecutorService或 ScheduledExecutorService实例。这里主要介绍这些不同特点的实例不同在什么地方。
- 3类不同的ExecutorService实例.
static ExecutorService newSingleThreadExecutor()
启动一个线程负责任务顺序执行,顺序意味着先提交的任务先执行。其原理是:任务会被提交到一个队列里,启动的那个线程会从队里里取任务,然后执行,执行完,再从队列里取下一个任务,再执行。如果该线程执行一个任务失败,并导致线程结束,系统会创建一个新的线程去执行队里里后续的任务,不会因为前面的任务有异常导致后面无辜的任务无法执行。
static ExecutorService newCachedThreadPool()
启动N个线程处理N个任务。既然是多个线程运行,意味着任务不会顺序运行。一个任务完成后,该线程空闲60秒会被结束。新提交的任务会发现空闲线程,并使用它,如果没有空闲线程可用则创建新线程。其实,这就是一个动态线程池。适合于规模比较小、创建较频繁的任务。
static ExecutorService newFixedThreadPool(int nThreads)
动态线程池不限制线程的数量,在有些情况下我们不希望线程数量不可控,则可以使用拥有固定线程数目的线程池。运作原理是:任务被提交到一个队列里排队,线程池里的空闲线程会把队列里的任务提出来执行,每个线程执行完一个任务后,就去队列里抓另一个任务出来执行。如果一个线程由于失败而终止,系统会创建另一个线程执行后续任务。
- 带ThreadFactory参数生成的ExecutorService实例。以上3种实例创建工作线程时都是用的默认的线程工厂类来创建。也可以指定自己的线程工厂类来创建,以newSingleThreadExecutor(ThreadFactory threadFactory)为例:
//你自己的实现 class YourselfThreadFactory implements ThreadFactory { public Thread newThread(Runnable r) { Thread thread = new Thread(r); doXXX; return thread; } }
- 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可以保证。
- 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
Concurrent包常用方法简介的更多相关文章
- java Concurrent包学习笔记(四):BlockingQueue
一.BlockingQueue概述 1.阻塞的含义 BlockingQueue即阻塞队列,从阻塞这个词可以看出,在某些情况下对阻塞队列的访问可能会造成阻塞.被阻塞的情况主要有如下两种: ,当一个线程对 ...
- java.util.concurrent包API学习笔记
newFixedThreadPool 创建一个固定大小的线程池. shutdown():用于关闭启动线程,如果不调用该语句,jvm不会关闭. awaitTermination():用于等待子线程结束, ...
- Java:concurrent包下面的Collection接口框架图( CopyOnWriteArraySet, CopyOnWriteArrayList,ConcurrentLinkedQueue,BlockingQueue)
Java集合大致可分为Set.List和Map三种体系,其中Set代表无序.不可重复的集合:List代表有序.重复的集合:而Map则代表具有映射关系的集合.Java 5之后,增加了Queue体系集合, ...
- java util 下的concurrent包
------------------------------------------java util 下的concurrent包--------并发包--------------------.jav ...
- java.util.concurrent包
在JavaSE5中,JUC(java.util.concurrent)包出现了 在java.util.concurrent包及其子包中,有了很多好玩的新东西: 1.执行器的概念和线程池的实现.Exec ...
- java concurrent包的学习(转)
java concurrent包的学习(转) http://my.oschina.net/adwangxiao/blog/110188 我们都知道,在JDK1.5之前,Java中要进行业务并发时,通常 ...
- commons-lang 包常用方法
package com.java.utils; import java.util.Iterator; import java.util.Map; import org.apache.commo ...
- 《java.util.concurrent 包源码阅读》 结束语
<java.util.concurrent 包源码阅读>系列文章已经全部写完了.开始的几篇文章是根据自己的读书笔记整理出来的(当时只阅读了部分的源代码),后面的大部分都是一边读源代码,一边 ...
- 《java.util.concurrent 包源码阅读》02 关于java.util.concurrent.atomic包
Aomic数据类型有四种类型:AomicBoolean, AomicInteger, AomicLong, 和AomicReferrence(针对Object的)以及它们的数组类型, 还有一个特殊的A ...
随机推荐
- activiti节点跳转
分享牛原创(尊重原创 转载对的时候第一行请注明,转载出处来自分享牛http://blog.csdn.net/qq_30739519) activiti使用的时候,通常需要跟业务紧密的结合在一起,有些业 ...
- JQuery 初探
放暑假了,终于有时间能学点前端的东西了.JQuery就是我第一个选择,锋利的JQuery.这本书真的很好.下面以一个ToggleButton形式的小例子开场吧. 引入JQuery库 在网页上引用JQu ...
- ROS连接ABB机械臂调试详细教程-ROS(indigo)和ABB RobotStudio 6.03.02-
在ROS industrial介绍中,给出了ROS和常用机械臂的连接方式.具体信息可以参考:http://wiki.ros.org/Industrial ROS连接ABB机械臂调试详细教程-ROS(i ...
- JSP自定义方法库
如果JSTL的方法库没有满足需要,可以使用自定义方法进行扩展 public class Function{ public static int length(Object obj){ //返回对象的长 ...
- Android Demo 下拉刷新+加载更多+滑动删除
小伙伴们在逛淘宝或者是各种app上,都可以看到这样的功能,下拉刷新和加载更多以及滑动删除,刷新,指刷洗之后使之变新,比喻突破旧的而创造出新的,比如在手机上浏览新闻的时候,使用下拉刷新的功能,我们可以第 ...
- android最新更新方法
使用SDK Manager更新时出现问题Failed to fetch URL https://dl-ssl.google.com/android/repository/repository-6.xm ...
- ROS_Kinetic_24 使用catkin_create_qt_pkg快速创建qt-ros功能包
使用catkin_create_qt_pkg快速创建qt-ros功能包 参考网址: qt_create:http://wiki.ros.org/qt_create qt_ros:https://git ...
- [mysql]一次主从数据不一致的问题解决过程
之前一篇: 主从更换ip之后重新建立同步 情况时这样的 昨天晚上主动2个机器都迁移了,然后今天才把主动重新连接上,但是从库的偏移量是从今天当前时刻开始的,也就是说虽然现在主动看似正常,其实是少了昨天的 ...
- (八十七)AutoLayout的简介与实例
AutoLayout是继AutoResizing之后的一种自动布局方法,解决了AutoResizing无法处理控件间相互关系的问题. AutoLayout在storyboard中通过底部工具条设置,底 ...
- UNIX环境高级编程——线程属性之并发度
并发度控制着用户级线程可以映射的内核线程或进程的数目.如果操作系统的实现在内核级的线程和用户级的线程之间保持一对一的映射,那么改变并发度并不会有什么效果,因为所有的用户级线程都可能被调度到.但是,如果 ...