美文网首页
JAVA线程池源码解析,之听爸爸的话

JAVA线程池源码解析,之听爸爸的话

作者: 北方教主 | 来源:发表于2018-03-23 00:19 被阅读41次

    以前我都不会去写这一类的文章,因为不知道能给我带来什么好处,不过据说唠叨可以预防老年痴呆。我现在每天有时间都会阅读阅读源码,阅读源码的好处,可以提升架构能力,看大神是如何抽象接口的,可以完善思维,看大神把每种情况想得多全面,可以学习优化性能,看大神是用什么方式优化性能的,多看源码可以少踩坑,如果你觉得这都不是你想要的,那你可以当成英文短文看了,经常阅读源码,可以提升语感,看外国电影会发现听力好了很多,可以减少看字幕的频率。

    比方说线程池是一个当时公司提个架构需求,下面开始我的表演。

    LEADER 爸爸: 嗨小伙子,我想弄个轮子,我扔给你一个任务你就给我把它做完就行,但是你不需要关心我怎么执行的。

    RD小屌丝:好的大哥,那就弄个最基础,我给你一个提交命令的接口就行

    于是RD小屌丝搞了线程池的最底层的架构就是Executor,它作用是执行提交过来的runnable命令,决定命令运行的方式,可以封装执行命令的线程的创建以及调度方式。RejectedExecutionException如果Executor无法接受执行这个命令的时候抛出异常;NullPointerException如果命令为null的时候抛出这个异常

    public interface Executor{

         void executor(Runnable command); 

    }

    ... ten minutes later...

    LEADER 爸爸:我觉得功能有点局限

    RD小屌丝:这么快就要加功能 T 。T

    LEADER 爸爸:你是不想写代码吗?我就问你抗揍不

    RD小屌丝:爸爸你说咱们还可以优化哪里?

    LEADER爸爸:可能我一次提交很多个任务,有可能我会想把这些任务全部关掉,有可能我想看一下这个执行器的状态,所以还需要定一个高配版本的执行器。

    RD小屌丝:没问题的爸爸

    于是小屌丝定义了,ExecutorService接口是对,ExecutorService接口是对Executor的扩展

    public interface ExecutorService extend Executor{

        void shutdown();/执行器不再接受后续发过来的命令。

        List shutdownNow()://执行器立即停止,还没轮上执行的命令不再执行了,正在执行的命令继续执行,然后将还没有被执行过的任务列表返回。

        boolean isShutdown();//返回线程池开关状态

        boolean isTerminated();//当shutdown调用完成后所有的任务都执行完毕以后返true,如果没有调用过shutdown的话其返回结果为false。

        boolean awaitTermination(long timeout,TimeUnit unit) throws InterruptedException, //阻塞当前线程,直到调用过shutdown后所有的任务都执行完成或者到达超时时间或者当前线程调用interrupted,当executor在超时时间内终止的话返回true否则返回false。

        Future submit(Callable task) //提交一个有返回值的任务,并且返回一个Future对象,当任务执行完成时候可以通过Future对象的get方法来获取任务的执行结果,当调用get方法时候会阻塞当前线程直到有结果传出,如果任务不能被调度与执行抛出RejectedExecutionException异常,如果任务为空的话抛出空指针异常。

        Futuresubmit(Runnable task,T result);//提交一个任务,然后返回一个用来代表这个任务的Future对象,Future对象的get方法会返回这个任务的执行结果,T返回结果的类型.    

        Futuresubmit(Runnable task);//当task执行成功后会返回一个null

        List> invokeAll(Collection>tasks, long timeout,TimeUnit unit)throws InterruptedException;//执行一组任务,然后返回一组控制这些任务的Future对象,如果任务没有执行完成就被取消的话会抛出InterruptedException

    }

    LEADER爸爸:我又想到了一些,有时候我还会对单个命名做些特殊处理

    RD小屌丝:(内心os,难以置信,竟然还有想法,你总想没用的,你咋不想吃屎呢)我觉的也是,比如说取消单个任务

    LEADER爸爸:你说的没错,取消任务执行,查看任务执行状态,是否执行完成,是否被取消等等,或者定时读取结果执行结果。

    于是RD小屌丝对任务单独定义了一个Future接口用来操作任务的执行,以下是一些关于Futrue的一些介绍

    public interface Future<V>  {

         //这个V是Future对象的返回值的类型,通过get()方法活的这个返回值,最重要的两个方法cancel方法和get方法

        boolean cancel(boolean mayInterruptIfRunning);//企图阻止任务的执行,如果任务不能被阻止或者已经执行完成返回false否则返回true;在这个方法调用后isDone()将一直返回true,如果这个方法返回true的话,那么isCanceled()方法就会一直返回true;mayInterruptIfRunning为true的话那么当任务正在执行中会中断任务线程的执行。

        boolean isCanceled();//当任务在执行完成之前成功被取消的话返回true

        boolean isDone();//当任务完成或者被取消或者产生异常终止都会返回true;

        V get();阻塞等待任务的执行结束,然后获取返回结果,如果等待过程中当前任务被canceled 会抛出cancellationException,任务执行过程中出错的话抛出 ExecutionException,如果当前线程被中断的话会抛出InterupedException

        V get(long timeOut,TimeUnit unit) ;最多阻塞等待timeout时间去获取返回的结果,抛出的异常与无参数get()方法相同,如果阻塞时间超时t还没有返回结果的话,抛出TimeoutException。

    }

    LEADER爸爸走后RD小屌丝陷入了思考,执行器只能执行任务,也没有返回值,我怎么跟踪执行取消任务呢,RD小屌丝想到了RunnableFuture接口,恩,我可以把任务和调度组成一个对象,这样就可以跟踪了,RD小屌丝沉迷于对自己智慧的大脑的迷恋中不能自拔,LEADER爸爸不在我就是我自己的王者。

    RunnableFuture接口继承了Runnable接口和Future接口,接口可以多继承


    不活到最后你永远不知道谁是最惨的,RD小屌丝找来了实习生小王讲解了接口定义过程

    RD小屌丝:小王现在前面的路我已经铺好了,后面就靠你了。

    于是有了后来的FutureTask 。。。。

    FutureTask实现了RunnableFuture接口,一个可取消执行的异步计算任务,这个类实现了Future接口,实现了开始执行任务方法和取消任务执行的方法,包括可以查看当前任务状态是否被取消,还可以当任务完成的时候活的任务的返回结果,返回数据通过get方法获取

    任务的运行状态:初始化的时候是NEW状态,state会在set方法中转变成最终状态,在完成时候,如果返回结果的话,state会被设置为 COMPLETEING,也有可能因为调用了cancel(true)时候设置为INTERUPTED

    private Callable callable;//在执行后会被设置为空

    private Object outcome //返回结果,或者是调用get方法时候抛出的异常

    private volatile Thread thread //执行callable的线程

    private volatile WaitNode waits;//保存等待的线程的链表结构

    private V report(int s) throws ExecutionException{

    Object x = outcome;

    if(s == NORMAL)return (V) x;//如果正常结束的话返回结果,否则抛出异常

    if(s> CANCELLED)

    throws new CancellationException();

    throws new ExecutionException((Throwable)x)

    }

    public FutureTask(Callable callable){

    if(callable == null) throws NullPointException;

    this.callable = callable;

    state = NEW;//更新状态确保状态的可见性

    }

    public FutureTask(Runnable runnable ,V result){//当成功执行完成时候如果你需要一个特别的返回值的时候可以获取这个result,如果不需要特别的result

    可以用 Future future = new FutureTask(runnable,null);

    this.callable = Executors.callable(runnable,result);

    state = NEW;

    }

    public boolean isCanceled(){

    return  state >= CANCELLED;)

    }

    public boolean isDone(){

    return state != NEW;

    }

    public boolean cancel(boolean mayInterruptIfRunning){

    if(!(state == NEW && U.compareAndSwapInt(this,state,NEW,mayInterruptIfRunning?INTERRUPTING:CANCALLED)))return false;//只有线程是new状态的时候是可以cancel的

    try{

    try{

    if(mayInterruptIfRunning){

    Thread t = runner;

    if(t!= null){

    t.interrupt();

    }

    }

    }finally{

    U.putOrderedInt(this,STATE,INTERRUPTED);//

    }

    }finally{

    finishCompletion();

    }

    }

    private finish completion() //释放所有等待结果的线程,并且唤醒这些线程通过LockSupport.unpark(t)方法,之后就是,调用done方法以及把当然的callable任务设置为空

    public void run(){

    if(state != NEW || U.compareAndSwapObject(this,RUNNER,null,Thread.currentThread()))return;//每一个任务只能执行一次

    int s = state;

    try{

    Callable c  = callable;

    if(c!= null&& s == NEW){

    boolean ran;//标志是否成功执行

    V result;//返回结果;

    try{

    result =c.call():

    ran = true;

    }catch(Throwable ex){

    ran = false;

    setException(ex)

    }

    if(ran)

    setResult();

    }

    }finally{

    runner = null;

    s = state;

    if(s >= INTERRUPTING){

    handlePossibleCancellationInterrupt(s)

    }

    }

    }

    protected void set(V v){

    if(U.compareAndSwapInt(this,STATE,NEW,COMPLETING)){

    outcome = v;

    U.putOrderedInt(this,STATE,COMPLETING,NORMAL);

    finishCompletion();

    }

    }

    private  void handllePossibleCancellationInterrupt(){

    //当调用cancel(true)在run方法中,如果run的时候恰巧要cancel那么就会释放这个cpu然后设置状态为INTERRUPTING,这时cancel方法finial代码块里会再把状态设置成INTERRUPTED

    if(s == INTERRUPTING){

    while(s == INTERRUPTING){

    Thread.yield();

    }

    }

    }

    public V get(long timeout,TimeUnit unit) throws InterruptException ,NullPointException,TimeOutException{

    if(unit == null) throws new NullPointException();

    if(s <= COMPLETING&& s = awaitDone(true, unit . toNanos(timeout)<= COMPLETING)) throws new TimeoutException():

    return report(s);

    }

    private int awaitDone(boolean timed , long nanos) throws InterruptException{

    long startTime = 0L;

    WaitNode q = null;

    boolean queued = false;

    for(;;){

    int s = state;

    if(s > COMPLETING){

    if(q != null){

    return s;

    }

    }

    else if (s == COMPLETING) Thread.yield();

    else if(Thread.interrupted()){

    removeWaiter(q);]

    throws new InterruptedException();

    }

    else if(q == null){

    if(time & nanos <0L)return s;

    q = new WaitNode();

    }

    else if(!queued)

    queued = U.compareAndSwapObject(this,WAITERS,q.next = waters,q)

    else if(timed){

    final long parkNanos;

    if(startTime == 0L){

    startTime = System.nanoTime()://计算需要睡眠的时间

    if(startTime == 0L)

    startTime = 1L;

    parkNanos = nanos;

    }else{

    long elapsed = System.nanoTime() - startTime;

    if(elapsed >= nanos){/如果超时了的话,那就返回结果

    removeWaiter(q);

    return state;

    }

    parkNanos = nanos - elapsed;//如果线程被意外唤醒,但是没到达时间的话,继续睡眠

    }

    if(state

    LockSupport.parkNanos(this,parkNanos)

    }else{

    LockSupport.park(this);

    }

    }

    }

    我们不讲社会主义价值观,说说现在的社会主义现象,我发现现在的社会主义剥削都是层层深入的。我是一个很有正义感的小仙女,此文中严厉谴责,leader和rd小屌丝,怎么官僚主义气息这么严重,不知道自己挖的坑自己埋的道理嘛?同时对小王遭遇深表同情,但我知道小王的目标是转正,然后他的梦想是以后像Leader爸爸一样神气,我此时遭的罪都会还给后辈,不信你参考年年大学军训,大二师哥师姐对军训的看法,历史车轮滚滚向前,时代潮流浩浩荡荡,你不能改变别人但是你可以改变自己,你不能改变现象,但是你可以改变发心,做一个受害者,就不要做一个施暴者。

    所以知道我讲的故事的用意是?一个大功能模块如何拆解?借口如何定义?

    送给大家一首江南第一风流才子,唐伯虎的诗

    桃花坞里桃花庵,桃花庵下桃花仙。

    桃花仙人种桃树,又摘桃花换酒钱。

    酒醒只在花前坐,酒醉还来花下眠。

    半醉半醒日复日,花落花开年复年。

    但愿老死花酒间,不愿鞠躬车马前。

    车尘马足富者事,酒盏花枝隐士缘。

    若将显者比隐士,一在平地一在天。

    若将花酒比车马,彼何碌碌我何闲。

    世人笑我太疯癫,我笑他人看不穿。

    不见五陵豪杰墓,无花无酒锄作田。

    集美貌与才华于一身的小仙女,papi酱的美貌与才华也被我征集过来了,我会给你怼我的机会,休想    ----by小仙女

    相关文章

      网友评论

          本文标题:JAVA线程池源码解析,之听爸爸的话

          本文链接:https://www.haomeiwen.com/subject/taftcftx.html