FutureTask 源码 并发设计模式

一、代码

【并发设计模式】FutureTask - 简书

	public static void main(String[] args) throws Exception {

		Callable<String> call = new Callable<String>() {

			@Override
			public String call() throws Exception {
				System.out.println("要花3秒时间去做的其他事");
				Thread.sleep(3000);
				System.out.println("已经做完了其他事");
				return "洗车";
			}
		};

		FutureTask<String> task = new FutureTask<>(call);

		Thread thread = new Thread(task);
		thread.start();

		// do something
		System.out.println("做的第一件事");

		String result = task.get();

		System.out.println("要做的其他事:" + result);

	}

}

1.分析

二、UML图

三、代码分析

这张图我们看到状态,那么我就先把状态说明下

看代码前,说明下几个重要的变量

  1. private volatile Thread runner:当前运行的线程
  2. private Object outcome:输出的内容
  3. private volatile WaitNode waiters:等待的节点
    1. static final class WaitNode {
          volatile Thread thread;//线程
          volatile WaitNode next;//下一个节点
          WaitNode() { thread = Thread.currentThread(); }//当前线程加入节点
      }

继续看代码

run方法

异常方法

finishCompletion

set方法

handlePossibleCancellationInterrupt

因为我们代码有调用task,get()方法,接下来我们看看get的源码

s = awaitDone(false, 0L);

removeWaiter(q);

private void removeWaiter(WaitNode node) {
    if (node != null) {
        //设置节点的线程为空,做删除标记
        node.thread = null;
        retry:
        for (;;) {          // restart on removeWaiter race
            for (WaitNode pred = null, q = waiters, s; q != null; q = s) {
                s = q.next;
                //thread不为空,continue
                if (q.thread != null)
                    pred = q;
                //thread为空且pred不为空
                else if (pred != null) {
                    //删除q
                    pred.next = s;
                    //检查一下pred的thread,如果被其他线程修改,retry outer loop
                    if (pred.thread == null) // check for race
                        continue retry;
                }
                //thread为空且pred为空说明q为栈顶,将q.next设置为栈顶,失败则retry
                else if (!UNSAFE.compareAndSwapObject(this, waitersOffset,
                                                      q, s))
                    continue retry;
            }
            break;
        }
    }
}

流程

1. 当节点进来,先让节点的线程设置为空,表示该节点已经删除了(该节点一定在waiters的链上)

2. 获取当前的节点q,

3 设置s为q的后继节点

4 如果当q节点的线程不是空(说明传过来的节点node 不是当前节点),设置pred变量表示q

5 q=s,q节点指向下一个节点。开始第二轮的for循环

6 设置s为q的后继节点(这个时候q为指针向前的节点),如果q的线程是空,说明该节点已经标记删除了

7 看q节点的前面节点pred是否为空,不为空,那么就删除q节点。如果前面节点的线程为空(标记删除),则前面节点也要被删除,说明跳转retry重新来;如果前面节点pred为空,说明q节点是栈顶,尝试将q的后继点击设置为栈顶(栈顶多线程竞争栈顶,所以失败就重来),失败就重新来过。

8一直遍历节点,直到节点遍历完(这个删除节点可以删除多个哦)

parkNanos(Object blocker, long nanos) 

park(Object blocker) 

report(s)

源码已经看完了,现在来对源码总体了解下,他是做什么?

四,如果接下来的代码还看不懂,建议还是改行吧,哈哈


public class Demo3 {


    public static void main(String[] args) throws Exception {

        System.out.println("main---: 当前线程是:" + Thread.currentThread());


        Callable<String> call = new Callable<String>() {
            @Override
            public String call() throws Exception {
                System.out.println("main---: 异步线程开启,当前线程是:" + Thread.currentThread());
                Thread.sleep(2000);
//                           if(1==1){
//                               throw  new RuntimeException("异常");
//                           }
                return "洗车";
            }
        };
        FutureTask3<String> task1 = new FutureTask3<>(call);





        Runnable Runnable=new Runnable(){

            @Override
            public void run() {
                Thread thread = new Thread(task1);
                thread.setName("01");
                thread.start();
                try {
                    System.out.println("main---run: 异步线程返回值:" + task1.get());
                } catch (ExecutionException e) {
                    e.printStackTrace();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        };


        Thread thread1 = new Thread(Runnable);
        thread1.setName("异步线程1");
        thread1.start();

        Thread thread2 = new Thread(Runnable);
        thread2.setName("异步线程2");
        thread2.start();

        Thread thread3 = new Thread(Runnable);
        thread3.setName("异步线程3");
        thread3.start();



    }

}

----------------
package com.roocon.demo;

import sun.misc.Unsafe;

import java.lang.reflect.Field;
import java.util.concurrent.*;
import java.util.concurrent.locks.LockSupport;

public class FutureTask3<V> implements RunnableFuture<V> {
    private volatile int state;//内存可见
    private static final int NEW = 0;
    private static final int COMPLETING = 1;
    private static final int NORMAL = 2;
    private static final int EXCEPTIONAL = 3;
    private static final int CANCELLED = 4;
    private static final int INTERRUPTING = 5;
    private static final int INTERRUPTED = 6;

    private Callable<V> callable;
    private Object outcome;
    private volatile Thread runner;

    private volatile WaitNode waiters;//内存可见

    public FutureTask3(Callable<V> callable) {
//        初始化callable
        this.callable = callable;

    }

    //状态变化
//        NEW-->COMPLETING-->NORMAL
//        NEW-->COMPLETING-->EXCEPTIONAL
//        NEW-->CANCELLED
//        NEW-->INTERRUPTING-->INTERRUPTED

    public void run() {
        //排除其他情况,只对new状态执行run方法
        //如果状态不是初始化或更新runner线程为主线程不成功,不执行run方法。
        System.out.println("run---: 当前线程是:" + Thread.currentThread());
        if (state != NEW || !UNSAFE.compareAndSwapObject(this, runnerOffset, null, Thread.currentThread())) {
            System.out.println("! run  ");
            return;
        }

        try {

            Callable<V> c = callable;//多线问题
            //只有new 才执行
            if (state == NEW && c != null) {

                System.out.println("run---:state == NEW");
                V result;
                boolean isSucess;//是否正常执行
                try {
                    System.out.println("run---:执行call");
                    result = c.call();
                    isSucess = true;

                } catch (Throwable e) {//call方法异常
                    result = null;
                    isSucess = false;
                    System.out.println("run---:setException");
                    setException(e);

                }
                if (isSucess) {
                    System.out.println("run---:执行set");
                    set(result);
                }
            }

        } finally {


        }


    }

    /**
     * @return void
     * @Author feizhou
     * @Description 状态 NEW  ---:COMPLETING
     * @Date 下午 11:37 2019/10/30 0030
     * @Param [result]
     **/

    private void set(V result) {
        //完成就等待状态变为>COMPLETING
        //为了防止状态一直是COMPLETING,所以当状态是COMPLETING的时候,需要立马变更为>COMPLETING状态
        try {
            Thread.sleep(2000);//等待waitDone阻塞线程,卡住set方法
            System.out.println("set---:-等待waitDone阻塞线程,卡住set方法,当前线程是:" + Thread.currentThread());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
            outcome = result;
            UNSAFE.putOrderedInt(this, stateOffset, NORMAL);
            //唤醒线程
            System.out.println("set---:-finishCompletion");
            finishCompletion();
        }


    }


    /**
     * @return void
     * @Author feizhou
     * @Description 异常处理
     * @Date 上午 12:34 2019/10/30 0030
     * @Param []
     **/

    private void setException(Throwable e) {
        System.out.println("setExpression---:当前线程是:" + Thread.currentThread());

        if (UNSAFE.compareAndSwapInt(this, stateOffset, NEW, COMPLETING)) {
            outcome = e;
            UNSAFE.putOrderedInt(this, stateOffset, EXCEPTIONAL);
            //唤醒线程
            System.out.println("setExpression---:finishCompletion");
            finishCompletion();

        }

    }

    /**
     * @return void
     * @Author feizhou
     * @Description 结束, 唤醒线程
     * @Date 上午 12:37 2019/10/30 0030
     * @Param []
     **/

    private void finishCompletion() {


        for (WaitNode q; (q = waiters) != null; ) {//唤醒所有的线程
            System.out.println("finishCompletion---:遍历每一个节点,唤醒每一个节点的线程");
            if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {//当节点设置为空
                for (; ; ) {
                    Thread t = q.thread;

                    System.out.println("finishCompletion---:当前节点是:" + q);
                    if (t != null) {//删除当前节点
                        System.out.println("finishCompletion---:唤醒被阻塞的线程:" + t);
                        q.thread = null;
                        //唤醒线程
                        LockSupport.unpark(t);
                    }
                    WaitNode next = q.next;
                    if (next == null) {//最后一个节点就跳出
                        System.out.println("finishCompletion---:最后一个节点就跳出finishCompletion方法");
                        break;
                    }
                    q.next = null;//断开节点连接
                    q = next;
                    System.out.println("finishCompletion---:断开q与下一个节点的连接,设置q为下一个节点");
                }
                //如果执行到这里,就跳出外面的for循环
                break;
            }

        }

        callable = null;

    }


    @Override
    public V get() throws ExecutionException, InterruptedException {
        System.out.println("get---: 当前线程是:" + Thread.currentThread());
        int s = state;
        if (s <= COMPLETING) {//还在执行中
            //阻塞当前进程
            System.out.println("get---: 执行awaitDone");
            s=awaitDone();
        }


        return report(s);
    }

    private V report(int s) throws ExecutionException {
        Object x = outcome;
        if (s == NORMAL)
            return (V)x;
        if (s >= CANCELLED)
            throw new CancellationException();
        throw new ExecutionException((Throwable)x);
    }


    //新增等待节点
    private int awaitDone() {
        WaitNode q = null;
        boolean queue = false;


        for (; ; ) {
            int s = state;
            System.out.println("awaitDone---:状态:" + s);
            if (s > COMPLETING) {
                System.out.println("awaitDone---:s > COMPLETING");
                if (q != null) {完成或者异常或者中断,就返回
                    q.thread = null;
                    return s;
                }

            } else if (s == COMPLETING) {
                System.out.println("awaitDone---:s == COMPLETING");
                //完成就等待状态变为>COMPLETING
                //为了防止状态一直是COMPLETING,所以当状态是COMPLETING的时候,需要立马变更为>COMPLETING状态,set有这样的操作
                Thread.yield();
            } else if (q == null) {
                System.out.println("awaitDone---:q == null");
                q = new WaitNode();
            } else if (!queue) {//直到加入节点尾部成功。
                queue = UNSAFE.compareAndSwapObject(this, waitersOffset, q.next = waiters, q);
                System.out.println("awaitDone---:waiters=" + waiters + ",queue:" + queue);

            } else {//状态是state1<COMPLETING
                //阻塞当前线程
                System.out.println("awaitDone---:阻塞当前线程是:" + Thread.currentThread());
                LockSupport.park(this);
            }


        }


    }


    @Override
    public boolean cancel(boolean mayInterruptIfRunning) {
        return false;
    }

    @Override
    public boolean isCancelled() {
        return false;
    }

    @Override
    public boolean isDone() {
        return false;
    }


    @Override
    public V get(long timeout, TimeUnit unit) throws ExecutionException {

        return (V) outcome;
    }


    static final class WaitNode {
        //主线程(阻塞主线程)
        volatile Thread thread;
        volatile WaitNode next;

        WaitNode() {
            //主线程
            thread = Thread.currentThread();
        }

        @Override
        public String toString() {
            return "WaitNode{" +
                    "thread=" + thread +
                    ", next=" + next +
                    '}';
        }
    }


    // Unsafe mechanics
    private static sun.misc.Unsafe UNSAFE;
    private static final long stateOffset;
    private static final long runnerOffset;
    private static final long waitersOffset;

    static {
        try {
            Field unsafeField = Unsafe.class.getDeclaredFields()[0];
            unsafeField.setAccessible(true);
            try {
                UNSAFE = (Unsafe) unsafeField.get(null);
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            Class<?> k = FutureTask.class;
            stateOffset = UNSAFE.objectFieldOffset
                    (k.getDeclaredField("state"));
            runnerOffset = UNSAFE.objectFieldOffset
                    (k.getDeclaredField("runner"));
            waitersOffset = UNSAFE.objectFieldOffset
                    (k.getDeclaredField("waiters"));
        } catch (Exception e) {
            throw new Error(e);
        }
    }

    @Override
    public String toString() {
        return "FutureTask3{" +
                "state=" + state +
                ", callable=" + callable +
                ", outcome=" + outcome +
                ", runner=" + runner +
                ", waiters=" + waiters +
                '}';
    }
}
------------
测试输出:

 
main---: 当前线程是:Thread[main,5,main]
get---: 当前线程是:Thread[异步线程2,5,main]
get---: 执行awaitDone
awaitDone---:状态:0
awaitDone---:q == null
run---: 当前线程是:Thread[01,5,main]
run---:state == NEW
run---:执行call
main---: 异步线程开启,当前线程是:Thread[01,5,main]
get---: 当前线程是:Thread[异步线程3,5,main]
get---: 执行awaitDone
awaitDone---:状态:0
awaitDone---:q == null
get---: 当前线程是:Thread[异步线程1,5,main]
get---: 执行awaitDone
awaitDone---:状态:0
awaitDone---:q == null
awaitDone---:状态:0
awaitDone---:状态:0
awaitDone---:waiters=WaitNode{thread=Thread[异步线程2,5,main], next=null},queue:true
awaitDone---:状态:0
awaitDone---:阻塞当前线程是:Thread[异步线程2,5,main]
awaitDone---:waiters=WaitNode{thread=Thread[异步线程1,5,main], next=WaitNode{thread=Thread[异步线程2,5,main], next=null}},queue:true
awaitDone---:状态:0
awaitDone---:阻塞当前线程是:Thread[异步线程1,5,main]
run---: 当前线程是:Thread[01,5,main]
! run  
awaitDone---:状态:0
awaitDone---:waiters=WaitNode{thread=Thread[异步线程3,5,main], next=WaitNode{thread=Thread[异步线程1,5,main], next=WaitNode{thread=Thread[异步线程2,5,main], next=null}}},queue:true
awaitDone---:状态:0
awaitDone---:阻塞当前线程是:Thread[异步线程3,5,main]
run---: 当前线程是:Thread[01,5,main]
! run  
run---:执行set
set---:-等待waitDone阻塞线程,卡住set方法,当前线程是:Thread[01,5,main]
set---:-finishCompletion
finishCompletion---:遍历每一个节点,唤醒每一个节点的线程
finishCompletion---:当前节点是:WaitNode{thread=Thread[异步线程3,5,main], next=WaitNode{thread=Thread[异步线程1,5,main], next=WaitNode{thread=Thread[异步线程2,5,main], next=null}}}
finishCompletion---:唤醒被阻塞的线程:Thread[异步线程3,5,main]
finishCompletion---:断开q与下一个节点的连接,设置q为下一个节点
finishCompletion---:当前节点是:WaitNode{thread=Thread[异步线程1,5,main], next=WaitNode{thread=Thread[异步线程2,5,main], next=null}}
finishCompletion---:唤醒被阻塞的线程:Thread[异步线程1,5,main]
finishCompletion---:断开q与下一个节点的连接,设置q为下一个节点
finishCompletion---:当前节点是:WaitNode{thread=Thread[异步线程2,5,main], next=null}
finishCompletion---:唤醒被阻塞的线程:Thread[异步线程2,5,main]
awaitDone---:状态:2
awaitDone---:s > COMPLETING
main---run: 异步线程返回值:洗车
awaitDone---:状态:2
awaitDone---:s > COMPLETING
main---run: 异步线程返回值:洗车
awaitDone---:状态:2
awaitDone---:s > COMPLETING
main---run: 异步线程返回值:洗车
finishCompletion---:最后一个节点就跳出finishCompletion方法

Process finished with exit code 0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值