搜狐媒体平台-搜狐网站 > 汪峰内疚陪女儿少:不向孩子隐瞒婚恋状况

榆横公安开展行业场所保安人员培训工作

抬头一看,玄衣那愤怒的眸子印入了一张十分年轻的脸庞,但是那一双眼睛却透露出看穿人心,历史的沧桑感,剑眉星目,明明不是超级帅气的类型,可是单单就是一双眼睛就能将极品帅哥都贬低下去,就连玄衣这样的成熟美妇都一瞬间失神。

国网榆阳供电公司高效服务用户

第二天的时候叶扬便是准备修炼了,他听从了蛊婆之言,要掌握自己的命运,即便是最后失败,那也是曾经努力过,不留任何的遗憾。他要好好的参悟一下那空间异能,看看能不能找到机会对乌鲁造成伤害。

newCachedThreadPool

长城网 阅读( 808) 评论( 0)
声明:本文由入驻搜狐公众平台的作者撰写,除搜狐官方账号外,观点仅代表作者本人,不代表搜狐立场。 举报

这时,他忽然听见了杨贵妃的声音,“这些冬天的东西就不要带走了,反正年底还要来,带回去也用不了,就留在这里吧!”

转发文章赚钱源码

“你真的以为自己有了神,召唤出了翼神龙就赢了吗?”孔雀舞摇了摇头:“你太依赖神的力量了,你将一切的希望都放在了神的身上,整个卡组都是为了神而服务,换句话说只要我打败了你的神,你就再也没有任何的希望了。”
其实去书房只是王元宝的一个借口,他需要一点时间思考对策,李庆安居然要和他合作,除了柜坊,李庆安还能和他合作什么?王元宝立刻想到了这几天安西柜坊的异常,他心中不由有些忐忑起来,他只是一个商人,涉足政治最多是想找个后台,他可不想真的参与到政治斗争中去,可李庆安他又惹不起,王元宝只得硬着头皮带胡云沛来他的书房。

叶扬心中此时颇有些郁闷,自己怎么那么糊涂啊,早知道就不要什么了,现在弄成了这么一个尴尬的局面。

ThreadPoolExecutor是JDK内置的线程池实现类,最初随JDK1.5发布。最近花了点时间看了下ThreadPoolExecutor的源码,JDK版本是JDK1.8.0_71。

整体结构

@startuml

class LinkedBlockingQueue
class SynchronousQueue
class Thread
class Worker
interface BlockingQueue
interface ThreadFactory
class ThreadPoolExecutor 
abstract class AbstractExecutorService
interface ExecutorService 
interface Executor 
 
Executor <|-- ExecutorService
ExecutorService <|.. AbstractExecutorService
AbstractExecutorService <|-- ThreadPoolExecutor 
ThreadPoolExecutor o-- ThreadFactory  
ThreadPoolExecutor o-- BlockingQueue  
ThreadPoolExecutor o-- Worker   
BlockingQueue <|-- SynchronousQueue 
BlockingQueue <|-- LinkedBlockingQueue 
Worker o-- Thread  
ThreadFactory <|-- Executors.DefaultThreadFactory  

@enduml

上面这张图展示了ThreadPoolExecutor的一个大致的类结构。

ThreadPoolExecutor当然依赖很多类,但最主要的还是三个大类ThreadFactory、BlockingQueue、Thread:

  • ThreadFactory。主要定义了创建线程的方式。这一块,用户可以自己定义线程的创建行为,例如调整线程的栈大小等。这应该是设计模式里的模版模式。
  • BlockingQueue。用来存放用户提交的、尚未开始执行的Runnable任务。当然BlockingQueue也未必真的有存储容量,例如SynchronousQueue。
  • Thread。线程池里当然有线程,这是句废话。不过ThreadPoolExecutor把Thread封装在一个私有类Worker里面。ThreadPoolExecutor和Worker既保持了良好的封装性,又是紧耦合。这一点不确定好还是不好,应该再体会体会。

创建方式

JDK在Executors类里面提供了若干工厂方法,可以方便地创建线程池。其中和ThreadPoolExecutor关联的工厂方法有:

  • newSingleThreadExecutor:创建单线程的线程池。主要用来实现异步调用。
  • newFixedThreadPool:创建固定线程数量的线程池。主要用于处理计算密集型任务。
  • newCachedThreadPool:这个线程池,能够按需创建线程。闲置的线程可以复用,避免创建开销。闲置超过60s的线程会被回收。主要用于处理能够快速返回的IO密集型任务。

ScheduledThreadPoolExecutor是ThreadPoolExecutor的子类,可以实现周期性的执行任务,这里暂不涉及。

这些工厂方法虽然方便,但是在业界被吐槽。《阿里Java编码规范》指出这些工厂方法的没什么可变参数,没什么调优的余地,而且自身的参数也不直观。试想一下,如果CachedThreadPool遇到密集的IO请求任务时,线程不断创建,最后会不会内存溢出呢?对于FixedThreadPool,如果任务量并不大,时刻保持固定数量的线程是不是有点浪费资源呢?所以说,创建线程池的最好的方法还是直接用ThreadPoolExecutor的构造器方法。

ThreadPoolExecutor的构造器有这些参数:

  • corePoolSize:线程池核心线程数量。
  • maximumPoolSize:线程池最大线程数量。
  • keepAliveTime:线程的闲置时间。
  • unit:线程限制时间单位。
  • workQueue:线程工作队列。
  • threadFactory:线程工厂。
  • RejectedExecutionHandler:RejectedExecution的捕获器。

运行时行为

ThreadPoolExecutor把所管理的线程分为两类。一类是核心线程,一类是非核心线程。

当一个ThreadPoolExecutor刚刚创建出来的时候,里面没有任何正在运行的线程。当开始提交任务的时候,线程池会首先创建核心线程。即是当前有闲置线程,如果线程总数低于corePoolSize,那么依然会创建新的线程来运行任务。这个阶段可以视为线程池处于“热身”阶段。ThreadPoolExecutor也提供了prestartCoreThread、ensurePrestart、prestartAllCoreThreads三个方法来手动实现“无任务热身”。

当线程总数达到corePoolSize同时所有线程都在运行时,继续提交的任务,就会交给workQueue来处理。其实调用的就是workQueue的offer方法。通常是将任务留在队列里面,开始排队。

随着任务持续提交,当队列中任务达到最大值的时候,线程池开始创建新的线程,来处理队列中的任务。随着线程不增加,当线程总数达到maximumPoolSize时,继续提交的任务会被线程池拒绝,抛出RejectedExecutionException运行时异常。默认情况下,异常交由任务提交方来处理。但是,用户也可以自定义RejectedExecutionHandler来统一处理该异常。

当任务处理完毕后,线程就会闲置起来。一直闲置着当然不是个事儿。线程会闲置keepAliveTime时间,随后销毁回收。

默认情况下,核心线程不会因为闲置超时而被回收。但这可以通过allowCoreThreadTimeOut方法来修改设置。

总的来讲,ThreadPoolExecutor会积极创建核心线程,对于非核心线程则是消极创建。

保持足够数量的核心线程是出于及时响应任务提交的需要。这个很好理解。

但是,消极创建非核心线程就不好理解了。我一直觉得,池内线程的数量应该与队列里的任务数量保持一种台阶式的准线性关系比较好。随着队列任务的增加,逐渐增加线程数量,这样系统能够保持在一个稳定的状态,比来回变化的线程数量和任务数量,应当更有利于GC的表现。当然了,这一块一直没有真正的去测试一下,就留作以后的一个课题吧。

源码阅读心得

这里说下我觉得值得注意的几点。

线程池状态管理

ThreadPoolExecutor对象有五个运行状态,使用int来表示:

状态 二进制数值 意义
RUNNING 11100000000000000000000000000000 正常运行
SHUTDOWN 00000000000000000000000000000000 不再接受新任务,但仍然在处理队列中的任务
STOP 00100000000000000000000000000000 不接受新任务,不处理队列任务,终止正在处理的任务
TIDYING 01000000000000000000000000000000 所有任务终止,线程数量归零
TERMINATED 01100000000000000000000000000000 terminated()方法执行完毕
  1. RUNNING状态可以到达SHUTDOWN状态,也可以直接到达STOP状态。
  2. 当然SHUTDOWN状态,也可以到达STOP状态。
  3. SHUTDOWN状态和STOP状态都可以到达TIDYING状态。
  4. TIDYING状态只能到达TERMINATED状态。

Java中整形变量最大是32个bit。ThreadPoolExecutor使用了最高的3个bit来表示当前线程池的状态,低位的29个bit用来表示当前池内的线程数。所以说,ThreadPoolExecutor支持的最大线程数为2^29=536_870_911。5亿多,想来应该是够用了。

ThreadPoolExecutor使用一个AtomicInteger变量来维护线程池状态。使用原子类型可以保证该变量能够高效的并发修改(相比于锁对象)并及时发布(这个有点类似于volatile的作用)。

ThreadPoolExecutor通过位的求或、求与、求反来实现对线程池状态和线程数量的查询。位运算,相比于算术运算,有更好的执行效率。这个可以好好研究下。

无阻塞算法的使用

ThreadPoolExecutor对象调用私有的addWorker方法来创建线程。

这个方法的内部最先是一个两层嵌套的for循环(labeled for-loop)。

private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.
            if (rs >= SHUTDOWN &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;

            for (;;) {
                int wc = workerCountOf(c);
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                c = ctl.get();  // Re-read ctl
                if (runStateOf(c) != rs)
                    continue retry;
                // else CAS failed due to workerCount change; retry inner loop
            }
        }
    ...
}

外部循环带有一个retry标签,而内部循环可以是正常退出,也可以是在外层循环框架下执行break、continue动作。这个语法很少用到,但在某些场景下会很有用,值得记一笔。

其实观察一下内层循环里,要想能够打破循环,继续执行下面的内容,必须成功的完成函数compareAndIncrementWorkerCount调用。这个方法是对线程池状态变量的原子化替换。多个外部线程同时调用该函数的时候,有且只会有一个线程成功执行,然后继续增加内部线程。成功完成原子量变更的前提是,从读取初始值、完成新值计算到准备变更之间,该原子量不能有变化,否则就会重现执行外层循环。

这实际上是一种乐观的无锁算法。

乐观的意思是,函数的执行倾向于认为变量的并发修改频率不大,自己总能足够快的完成函数执行。

无锁,就很好理解了。各个线程不需要阻塞在锁对象上。如果一次执行失败,那就再来一次好了。少量for循环的开销比若干线程的阻塞和唤醒所带来的开销划算多了。

其实注意观察一下,这个方法和ReentrantLock类的tryLock方法都是乐观算法。两者共同的套路是,无限循环中包含一个试错条件,也就是使用一个原子变量的CAS(Coompare & Swap)操作作为成功与否的标记。如果成功,就会退出循环;如果失败,就会再循环一次。

在并发量不够高的场景下,无阻塞算法可以显著降低同步开销,与使用锁的算法相比,有更高的吞吐量。但是,如果并发量极高的时候,有锁反而更好。因为在后者场景下,无阻塞算法会有很多轮无效for循环,反而不如有序地获取锁来的高效。其实,这个可以用道路交通来类比:在车流量不大的路口,环岛的通过率更高;但当车流量很大的时候,红绿灯的效率更高。

线程池对象的全局锁对象

ThreadPoolExecutor对象内部有一把全局锁。这把锁会在,调用内部线程增加或者回收的时候调用,也会在读取线程池状态的时候调用。因此要注意这之间内部存在的阻塞关系。

此外,设想一种场景。所有线程全都在运行,队列满负荷运行,外部还有任务持续提交。如果此时线程运行中大量的抛异常退出,那么线程池会不停的创建线程、处理线程退出,这个行为就会被全局锁阻塞,导致线程池的低效运转。

要小心这种情况的发生。

队列任务的获取

ThreadPoolExecutor对象通过BlockingQueue获取任务。正如其名,BlockingQueue是一种阻塞式的队列。ArrayBlockingQueue、LinkedBlockQueue、PriorityBlockingQueue使用显式的锁对象,保护每一次队列任务的读取和放置;而SynchronousQueue则是将访问线程排队park起来,然后依次唤醒(unpark)提交或者获取任务。

频繁的读取BlockingQueue里的任务,会造成池内线程消耗大量时间在队列内部的同步机制上。因此,为了降低同步开销的比例,队列内部的任务不易快速返回。而出于吞吐量的考虑,队列内部的任务又不易消耗过长时间。这两者需要小心的平衡。

JDK1.7引入了新的LinkedTransferQueue据说有更好的并发效率。这个随后得花时间看看。

不要中途修改基础参数

尽管ThreadPoolExecutor对象可以在对象运行过程中,实时地修改corePoolSize、keepAliveTime等参数。但是修改这些参数,会在内部interupt所有线程,包括正在运行的线程。通常情况下,一般的业务逻辑不大会特别的处理InterruptedException。所以应该尽量避免在运行时修改线程池设置参数。

编辑:平纯侯陵

当前文章:http://weineike.biz/p8vdr/

发布时间:2018-11-21 14:39:48

网络赚钱偏门项目 在家网上赚钱的工作 我的世界后台挂机 安卓手杀三国杀 苹果手机怎么上不了网 现在开网店挣钱吗 容易付app推广赚钱 乐才官网登录

mt.sohu.com true 搜狐媒体平台 http://mt.sohu.com/20160717/n459636222.shtml report 1760 新华社长春7月17日电题:“互联网+”推动IT人才全行业增长高校专业“冷热”看经济变迁新华社记者李双溪近日,全国一本录取接近尾声。吉林大学招生办主任刘鹤表示,近
  • 热点视频
  • 影视剧
  • 综艺
  • 原创

洛阳矫卑集团

叶扬忍不住翻了翻白眼,这个家伙还真是什么理由都有。不过这刘一半要是拿鬼来吓唬他可真是大错特错了,他又不是没见过鬼魂。

济宁内黑僬科技有限公司

“给我打!”韩非怒了,手中的二十响盒子炮开火了,鬼子真恶毒,竟然派出来女人和小孩来当炮灰,刚才要不是自己怔住了,那身边的那两个小分队兄弟们就不会死!

安顺禄当网络科技有限公司

马楚这时候方有时机把安可晴拒了《爱的主打歌》,想请他帮忙写一首《默》类型歌的消息告知二。

通辽殖杭跆拳道俱乐部

那人咳嗽一声,发出气息越发微弱,“就算用过又如何,难道就凭这点血腥味猜出?”

我来说两句排行榜

1764
裴柔迟疑了一下,走上前问李庆安道:“他所说的是真话吗?这两个小娘是你的女人?”[ ]
1764
纪太虚面色不善:“白鬼神!这个该死的!”纪太虚一脚将支太皇踢到烛龙宝鼎之中而后对着白鬼神右手轻轻举起,手中拿着一道闪动着灿烂星光的宝符:“如今恐怕北风已起,侯爷我还有要事,后会有期!”而后但见星光一闪,纪太虚便不见了踪影。支太皇事前布下的禁制竟然是毫无用处。[ ]
1764
而且这还不是最可怕的,万一被这倒刺刺中,植物里的毒液便会注射到你的体内。虽然不知道这植物中是什么毒素,但却绝对不好玩。[ ]
1764
明珠见姐姐在李庆安面前揭了自己的老底,不由讪讪道:“不是路上无聊吗?要去渭南县啊!”[ ]
1764
“我可以一个人独自面对三个邪神,可以在和他们一次次的斗争当中不倒下,最终得到邪神的认可,单凭你一个幻神翼神龙就想反噬我,今天我就将你彻底的打服,让你知道你只是一个失败的神,既然是输给了我,那么就给我乖乖听话。[ ]
1764
那么好的材料制造而成的一套后天灵宝品质的神器发挥出来的作用居然只能压过一件等同品质的后天灵宝,如果是两件后天灵宝的话发挥出来的威能完全超过阿瑞斯这一套同等品质的神器。[ ]
1764
“这样。”郭晓眉头一皱,动过心思,不甘心留在这里,别看是边军首领手握大权,平日里处处受气,首先是粮饷,人员调动,都是兵部、户部的那些老爷们说了算,懂得打点关系的,自然好处多多,郭晓这种人仗着军功在身,根本不把这些人放在眼里,当然吃亏的只是自己,是不是还要受府令的欺负,日子必然不好过。[ ]
1764
他们走进了西岭巷,前面小巷深处便是热海居了,他记得上次那个姓常的东主是碎叶汉人,好像在碎叶还颇为地位,说不定他能帮自己补好最后的身世漏洞。[ ]
1764
那些丫鬟立刻停住了脚步:“适才纪将军来过了,将宁姑娘医治好了。”[ ]
1764
果然,随着戴沐白的解释,海马斗罗的脸色缓和过来,随意的问了一句,“既然你们出身不同,甚至是天南海北。那又为什么能够聚集在一起呢?”[ ]

客服热线:86-10-58511234

客服邮箱: kf@vip.sohu.com