Executor与Task的耦合性

1,除非线程池很非常大,否则一个Task不要依赖同一个线程服务中的另外一个Task,因为这样容易造成死锁;

2,线程的执行是并行的,所以在设计Task的时候要考虑到线程安全问题。如果你认为只会在单任务线程的Executor中运行的话,从设计上讲这就已经耦合了。

3,长时间的任务有可能会影响到其他任务的执行效率,可以让其他线程在等待的时候限定一下等待时间。不要无限制地等待下去。

确定线程池的大小

给出如下定义:

要使CPU达到期望的使用率,线程池的大小应设置为:

约等于Ncpu+1。

定制线程池

通过Executor来创建的线程池其实是预先给我们打造好的线程池,例如:

如果不能满足需求,可以自己量身定做:

    public ThreadPoolExecutor(int corePoolSize, //基本大小,没有执行任务时线程池的大小
int maximumPoolSize, //最大任务数量
long keepAliveTime, //最大空闲时间,超时后会被回收
TimeUnit unit,
BlockingQueue<Runnable> workQueue) {
//...
}

任务队列:缓存任务

前面有说到,使用线程池的好处是可以限制线程的数量,因此保证服务器不会被超量的线程给拖垮。当并发请求增加,我们不再是盲目地创建线程了。而是简单地创建一个任务缓存到处理队列中了。那么问题来了,当并发请求继续激增,服务线程无法消化任务,造成大量的任务堆积到队列中。这也是会消耗服务器资源的。

我们需要让服务器实在忙不过来的时候,扔掉一些请求。以保证自己不会奔溃。该放手的时候一定要放手,不是每个人都能随随便便造一个航天飞船发上天啊。服务器真的应付不过来的时候最重要的是要保护好自己。

创建线程池的时候,可以自己指定任务队列:

无界队列:就是创建队列的时候不设置大小;

有界队列:通上设置一个大小;

同步交换队列:SynchronousQueue,严格意义上说,它并不是真的队列,它只是一种数据交换的工具。任务来之后,这个队列直接把任务交给线程池中的一个线程。如果没有可用线程,则创建一个线程。如果不能创建了会拒绝这个任务。同步交换队列的核心就是它不缓存任务,要么线程池足够大,要么就直接拒绝。用于线程池可以无限增长或不会出现任务激增的场景。

可以用PriorityBlockingQueue来实现任务的排序。

饱和策略:任务队列中都存不了了怎么办

线程池提供了多种处理办法:

Abort:终止,对外抛RejectedExecutionException;

Discard:悄悄抛弃,注意是悄悄地,客户端根本不会知道自己提交的任务根本就没运行;

DiscardOldest:抛弃最老的,如果使用的是优先队列,被抛弃的会是优先级最高的那个(所以DiscardOldest不要和优先队列搭配使用)。

Caller-Runs:用客户端线程来直接运行任务代码。就是哪个线程在往线程池扔任务,那么就用这个线程来直接跑这个任务。这么做的好处是,让客户端分担线程池的负担,更主要的是让客户端先忙一会儿别的,从而暂停往线程池提交任务的动作。以期望线程池能最终缓过来。客户端都来帮着线程池做事了,那它自己的事肯定也就没人做了。如果客户端代码是一个Web请求处理程序,那么它将不再accpet新的请求,这些新的请求会被堵在TCP的缓存中,如果系统一直没有缓过劲来,再继续发展下去,就会把“过载”的信息弥漫到TCP的调用端了。整个这套设计的潜台词是“我们已经尽力了”。系统不会硬着陆直接挂掉,如果请求压力放缓,系统还是可以扛过来的。

线程工厂:定制线程

可以自己实现线程工厂来构建线程变量,从而定义更多需要的信息。

扩展ThreadPoolExecutor

ThreadPoolExecutor有一些生命周期的方法:beforeExecute、afterExecute和terminated。可以重写这些方法,实现统计和监控的功能。

递归算法的并行化

什么样的情况可以并行?

比如for循环去做一些事情,而这些事情是相互独立的。那么这些事情其实可以并行来做的(for循环是串行执行)。

这给我们的编程提供了新的思路,很多写了很多遍、平淡无奇的代码其实有更有趣的实现方式。

Java并发编程实践读书笔记(5) 线程池的使用的更多相关文章

  1. Java并发编程实践(读书笔记) 任务执行(未完)

    任务的定义 大多数并发程序都是围绕任务进行管理的.任务就是抽象和离散的工作单元.   任务的执行策略 1.顺序的执行任务 这种策略的特点是一般只有按顺序处理到来的任务.一次只能处理一个任务,后来其它任 ...

  2. Java并发编程实践读书笔记(3)任务执行

    类似于Web服务器这种多任务情况时,不可能只用一个线程来对外提供服务.这样效率和吞吐量都太低. 但是也不能来一个请求就创建一个线程,因为创建线程的成本很高,系统能创建的线程数量是有限的. 于是Exec ...

  3. Java并发编程实践读书笔记(1)线程安全性和对象的共享

    2.线程的安全性 2.1什么是线程安全 在多个线程访问的时候,程序还能"正确",那就是线程安全的. 无状态(可以理解为没有字段的类)的对象一定是线程安全的. 2.2 原子性 典型的 ...

  4. Java并发编程实践读书笔记(2)多线程基础组件

    同步容器 同步容器是指那些对所有的操作都进行加锁(synchronize)的容器.比如Vector.HashTable和Collections.synchronizedXXX返回系列对象: 可以看到, ...

  5. Java并发编程实践读书笔记(4)任务取消和关闭

    任务的取消 中断传递原理 Java中没有抢占式中断,就是武力让线程直接中断. Java中的中断可以理解为就是一种简单的消息机制.某个线程可以向其他线程发送消息,告诉你“你应该中断了”.收到这条消息的线 ...

  6. Java并发编程(您不知道的线程池操作)

    Java并发编程(您不知道的线程池操作) 这几篇博客,一直在谈线程,设想一下这个场景,如果并发的线程很多,然而每个线程如果执行的时间很多的话,这样的话,就会大量的降低系统的效率.这时候就可以采用线程池 ...

  7. Java并发编程(您不知道的线程池操作), 最受欢迎的 8 位 Java 大师,Java并发包中的同步队列SynchronousQueue实现原理

    Java_并发编程培训 java并发程序设计教程 JUC Exchanger 一.概述 Exchanger 可以在对中对元素进行配对和交换的线程的同步点.每个线程将条目上的某个方法呈现给 exchan ...

  8. Java并发编程实战 读书笔记(二)

    关于发布和逸出 并发编程实践中,this引用逃逸("this"escape)是指对象还没有构造完成,它的this引用就被发布出去了.这是危及到线程安全的,因为其他线程有可能通过这个 ...

  9. 《Java并发编程实战》第八章 线程池的使用 读书笔记

    一.在任务与运行策略之间的隐性解耦 有些类型的任务须要明白地指定运行策略,包含: . 依赖性任务.依赖关系对运行策略造成约束.须要注意活跃性问题. 要求线程池足够大,确保任务都能放入. . 使用线程封 ...

随机推荐

  1. db2 存储过程中的玩意

    aix的top是topas.vmstat也是一个玩意,但是不懂. AND C_DEP_CDE  like  substr(I_C_DPT_CDE,1,2)||'%';--db2中字符串的加法用||这个 ...

  2. 构造函数constructor 与析构函数destructor(五)

    我们知道当调用默认拷贝构造函数时,一个对象对另一个对象初始化时,这时的赋值时逐成员赋值.这就是浅拷贝,当成员变量有指针时,浅拷贝就会在析构函数那里出现问题.例如下面的例子: //test.h #ifn ...

  3. SQL之mysql常用操作语句(入门级)

    1.进入数据库: mysql -u root -p mysql -h localhost -u root -p database_name 2.列出数据库 show databases; 3.选择数据 ...

  4. c#中关于变量声明那么点事

    class MyVar { /* * 基于安全的考虑,c#变量的初始化有一定的要求 * 1.所有的局部变量在被显示的初始化之前,都会被编译器当作未初始化,然后抛出编译期出错; * 2.所有的字段级变量 ...

  5. 20155218 2016-2017-2 《Java程序设计》第6周学习总结

    20155218 2016-2017-2 <Java程序设计>第6周学习总结 教材学习内容总结 Java将输入/输出抽象化为串流,数据有来源及目的地,衔接两者的是串流对象. dump()方 ...

  6. javascript实现责任链设计模式

    javascript实现责任链设计模式 使多个对象都有机会处理请求,从而避免请求的发送者和接受者之间的耦合关系.将这些对象连成一条链,并沿这条链传递该请求,直到有一个对象处理他为止. 这是Gof的定义 ...

  7. android插件化简述

    2015年是Android插件化技术突飞猛进的一年,随着业务的发展各大厂商都碰到了Android Native平台的瓶颈: 从技术上讲,业务逻辑的复杂导致代码量急剧膨胀,各大厂商陆续出到65535方法 ...

  8. 集合(三)CopyOnWriteArrayList

    第一次见到CopyOnWriteArrayList,是在研究JDBC的时候,每一个数据库的Driver都是维护在一个CopyOnWriteArrayList中的,为了证明这一点,贴两段代码,第一段在c ...

  9. 在EBS里新建一个OU的步骤

    http://blog.csdn.net/kevingao/archive/2010/09/11/5877092.aspx 在EBS里新建一个OU的步骤1. 建立OU组织,关联SOB,LE2. 系统管 ...

  10. 教程-Delphi调用百度地图API(XE8+WIN7)

    unit U_map; interface //---------------------------------------------------// //----------COPY BY 无言 ...