线程池:Execution框架

摘要:
1线程池在Java中,任务执行的主要抽象不是线程,而是执行器。线程池中的任务可能已经完成,可能正在运行,其他任务正在队列中等待执行。}您可以关闭ExecutorService,这将导致它拒绝新任务。应关闭未使用的ExecutorServices,以便回收其资源。执行。shutdown();ExecutorService线程池Java并发编程-Executor框架1.3被延迟,并定期执行任务。newScheduledThreadPoolTimer:1存在问题。只能创建一个线程来执行所有计时器任务。2Runnable、Future和CallBack2.1 RunnableExecutor框架可以轻松定制执行策略。但是,要使用它,您的任务还必须实现Runnable接口。

每问题每线程:在于它没有对已创建线程的数量进行任何限制,除非对客户端能够抛出的请求速率进行限制。

下边 有些图片看不到,清看原地址:http://www.360doc.com/content/10/1027/21/495229_64583490.shtml

无限制创建线程的缺点:

1.线程生命周期的开销:线程的创建和关闭并不是“免费的”。

2.资源消耗量:活动线程会消耗系统资源,尤其是内存。

3.稳定性。

1线程池(ThreadPool

在java中,任务执行的首要抽象不是Thread,而是Executor

publicinterfaceExecutor{

/**

*Executor只是一个简单的接口,但是他却为一个灵活而且强大的框架创造了基础。

*/

voidexecute(Runnablecommand);

}

这个框架可以用于异步任务执行,而且支持很多不同类型的任务执行策略。它还为任务提交和任务执行之间的解耦提供了标准的方法。另外,还提供了对生命周期的支持以及钩子函数,可以添加诸如统计收集、应用程序管理机制和监视器等扩展。

1.1创建/关闭

1.newCachedThreadPool

创建可缓存的线程池,多的话回收,少的话增加,没有限制

N2.ewFixedThreadPool(intnThreads)

创建定长的线程池,每提交一个任务就创建一个线程,直到最大。如果某个以外终止,会补充一个新的

3.newScheduledThreadPool(intcorePoolSize)

定长线程池,而且支持定时的以及周期性的任务执行。相当于timer

4.newSingleThreadExecutor()

单线程化的executor,只创建唯一的工作线程来之心吧任务。如果它意外结束,会有另一个取代它。它会保证任务队列所规定的顺序执行。

5.newSingleThreadScheduledExecutor()

创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期地执行。

privatestaticfinalExecutor

exec=Executors.newFixedThreadPool(100);

ServerSocketsocket=newServerSocket(80);

while(true){

finalSocketconnection=socket.accept();

Runnabletask=newRunnable(){

publicvoidrun(){

handleRequest(connection);

}

};

exec.execute(exec);

}

1.2ExecutorService

线程如果无法正常关闭,则会阻止JVM的结束。线程池中的任务,可能已经完成,可能正在运行,其他还有在队列中等待执行。关闭的时候可能平缓的关闭,到唐突的关闭(拔掉电源)。为了解决生命周期的问题,ExecutorService扩展了Executor,并且添加了一些用于生命周期管理的方法。

publicinterfaceExecutorServiceextendsExecutor{

voidshutdown();

List<Runnable>shutdownNow();

booleanisShutdown();

booleanisTerminated();

booleanawaitTermination(longtimeout,TimeUnitunit)

throwsInterruptedException;

。。。。。

}

可以关闭ExecutorService,这将导致其拒绝新任务。提供两个方法来关闭ExecutorServiceshutdown()方法在终止前允许执行以前提交的任务,而shutdownNow()方法阻止等待任务启动并试图停止当前正在执行的任务。在终止时,执行程序没有任务在执行,也没有任务在等待执行,并且无法提交新任务。应该关闭未使用的ExecutorService以允许回收其资源。

exec.shutdown();

ExecutorService线程池

java并发编程-Executor框架

1.3延迟,并且周期性的任务,newScheduledThreadPool

Timer的问题:

1.只能创建唯一的线程来执行所有timer任务。

2.如果一个timerTask很耗时,会导致其他TimerTask的时效准确性出问题

3.如果TimerTask抛出未检查的异常,Timer将会产生无法预料的行为。Timer不会重新恢复。另外一个Timer中的Task出现异常以后,后面再给这个Timer的任务也将会无法执行。

1.4结合DelayQueue

如果要自己构建调度服务,那还可以考虑使用DelayQueue,它里面的每个对象低耦合一个延迟时间有关联,只有过期以后,DelayQueue才能让你执行take操作获取元素。那么当它里面的对象是FutureTask的时候,就可以构成一个简单的调度队列。

2RunnableFutureCallBack

2.1Runnable

Executor框架让定制一个执行策略变得简单,不过想要使用它,你的任务还必须实现Runnable接口。在许多服务器请求中,都存在一个情况,那就是:单一的客户请求。它能执行一些简单的任务,但是他不能返回一个值或者抛出受检查的异常。

2.2Callback

很多任务都会引起计算延迟,包括执行数据库查询、从网络上获取资源、进行复杂的计算。这些任务Callback抽象更好。它也可以被Executor框架执行

线程池:Execution框架第1张

Executors包含很多静态方法,可以吧RunnablePrivilegedAction封装为Callable

线程池:Execution框架第2张

2.3FutureTask

RunnableCallable描述的是抽象的计算性任务,这些任务通常是有限的,他们有开始,而且最终会结束。

一个Executor执行的任务有4个周期,创建、提交、开始、完成。由于任务的执行会花很长时间,我们也希望可以取消任务。

Future描述了任务的生命周期,并提供了相关的方法来获得任务的结果、取消任务以及检验任务是否完成还是取消。对应的isDoneisCancelled()方法,它不能后退,一旦完成,就永远停在完成状态上。用get(等待)获得结果。

/**

*@paramargs

*@throwsInterruptedException

*@throwsExecutionException

*/

publicstaticvoidmain(String[]args)throws

InterruptedException{

intthreadCounts=19;//使用的线程数

longsum=0;

ExecutorServiceexec=Executors.newFixedThreadPool(threadCounts);

List<Callable<Long>>callList=newArrayList<Callable<Long>>();

//生成很大的List

List<Integer>list=newArrayList<Integer>();

for(inti=0;i<=1000000;i++){

list.add(i);

}

intlen=list.size()/threadCounts;//平均分割List

//List中的数量没有线程数多(很少存在)

if(len==0){

threadCounts=list.size();//采用一个线程处理List中的一个元素

len=list.size()/threadCounts;//重新平均分割List

}

for(inti=0;i<threadCounts;i++){

finalList<Integer>subList;

if(i==threadCounts-1){

subList=list.subList(i*len,list.size());

}else{

subList=list.subList(i*len,

len*(i+1)>list.size()?list.size():len

*(i+1));

}

//采用匿名内部类实现

callList.add(newCallable<Long>(){

publicLongcall()throwsException{

longsubSum=0L;

for(Integeri:subList){

subSum+=i;

}

System.out.println("分配给线程:"

+Thread.currentThread().getName()

+"那一部分List的整数和为: SubSum:"+subSum);

returnsubSum;

}

});

}

List<Future<Long>>futureList=exec.invokeAll(callList);

for(Future<Long>future:futureList){

sum+=future.get();

}

exec.shutdown();

System.out.println(sum);

}

2.4和Service的结合

RunnableCallable类都可以通过Servicesubmit方法提交,并且返回一个Future,它表示这个任务,可以获得该任务的执行结果或者取消它。

线程池:Execution框架第3张

另外,可以给为Runnable/Callable显示的实例化一个FutureTask

CallablepAccount=newPrivateAccount();

FutureTaskfutureTask=newFutureTask(pAccount);

线程池:Execution框架第4张

3CompletionService

向Executor提交一个批处理任务,并且希望获得结果,那么你将会使用Future,然后不断的调用isDone来检验是否完成,这样太麻烦,还有更好的方法,那就是完成服务,CompletionServicepoll方法不会等待,返回nulltake方法会等待

它整合了ExecutorBlockingQueue的功能,你可以将Callable任务交给他执行,然后使用类似于队列中的takepoll方法,在结果完整时可用时获得这个结果。ExecutorCompletionService是它的实现类

它的实现也比较简单,在构造函数中创建一个BlockingQueue,用它保存结果:

privatefinalBlockingQueue<Future<V>>completionQueue;

提交的任务被包装成QueueFuture

privateclassQueueingFutureextendsFutureTask<Void>{

QueueingFuture(RunnableFuture<V>task){

super(task,null);

this.task=task;

}

protectedvoiddone(){completionQueue.add(task);}

privatefinalFuture<V>task;

}

覆写done方法,将结果置入BlockingQueue

它与上面获得一堆FutureTask,然后遍历的去get等返回还不一样。它只能一个个获取,代表有一个拿一个。FutureTaskget可能后面的FutureTask都已经好了,可是有一个还没好,那就卡在中间了

免责声明:文章转载自《线程池:Execution框架》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇Lua习题练习(9*9乘法表,输出所指定的图像,斐波那契数列)找重复数下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

ibatis 批量插入

  ibatis 批量插入 CreationTime--2018年7月2日10点21分 Author:Marydon 1.说明   基于oracle的sql语句 2.主键id有默认值,比如:sys_guid()   id有默认值的情况下,插入的时候,不再声明该字段,当插入一条数据的时候,oracle会自动生成id。 <insert id="inse...

python(元组)

元组 Python 的元组与列表类似,不同之处在于元组的元素不能修改。 元组使用小括号 ( ),列表使用方括号 [ ]。 元组创建很简单,只需要在括号中添加元素,并使用逗号隔开即可 创建一个元组 A = (1,2,'python','happy') #括号内可不输入内容,即为空元组 B = 1,2,3,'nice'...

FCL研究-集合- System.Collections 接口和对象集合

【目录】 发现自己已经有很长一段时间写代码没什么进步了,随便读读FCL的源码,看看之前一直用的方法是如何实现的,也顺便提高下自己。FCL很是庞大,很难下口,于是用最笨的办法,先看常见的命名空间,逐个展开。战五渣的水平,必定有很多理解上的错误,欢迎斧正,不胜感激。 System.Collections 命名空间中的集合包含(如列表、队列、位数组、哈希表和字...

CountDownLatch实例的await()方法

转自:http://blog.sina.com.cn/s/blog_4bed7e340101atnf.html 两年前写的程序,出了一个当时觉得莫名其妙的bug,就是线程偶尔会死掉,当时也看不出有什么问题所以当时的对策是起了一个监控线程,发现线程死掉就重启一个今天回头再去看这段代码,发现确实有漏洞代码如下public void startOneBusine...

从O365中获取users到D365中 使用flow

在我上篇blog中讲解到了怎么用代码把O365 users 获取到D365中. 从O365中获取users到D365中  这几天一直在研究flow, 发现flow可以更简单的完成这个功能. 一开始没有考虑用flow是因为flow获取所有用户的方式比较困难, 需要有个workaround (首先需要把所有用户添加到一个group当中,然后获取group me...

lua工具库penlight--02表和数组

类Python的List lua的优美之处在于把数组和关联数组都用table实现了(Python中叫list和dict,C++中叫vector和map)。 一般我们把数字索引的table叫做list。penlight里的List模仿了Python,看起来从Python借鉴是个好主意。 下面是一个List的例子,List实现了__tostirng,因此可以输...