FutureTask类源码的解析和Callable的使用

package cn.liu.thread;

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * https://blog.csdn.net/imxutao/article/details/79672337
 * @author Dick
 *
 */
public class Demo3 implements Callable<String>{
	private int total = 20;
	
	@Override
	public String call() throws Exception {
		while(total>0) {
			System.out.println(Thread.currentThread().getName()+": "+total);
			total--;
		}
		return "no tatal";
	}
	
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		FutureTask<String> thread = new FutureTask<>(new Demo3());
		new Thread(thread,"one").start();
		new Thread(thread,"two").start();
		System.out.println(thread.get());
	}
}

 在我的预期当执行结果应该是one和two交替执行。但是却不是。

但是Runnable却这样可以

package cn.liu.thread;

public class Demo2 implements Runnable{
	private int i = 20;
	@Override
	public void run() {
		while(i>0) {
			System.out.println(Thread.currentThread().getName()+i);
			i--;
		}
	}
	
	public static void main(String[] args) {		
		Demo2 t = new Demo2();
		//把t对象交给Thread来创建一个线程
		new Thread(t,"one").start();
		new Thread(t,"two").start();	
		}
}


public class FutureTask<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;

    
    @SuppressWarnings("unchecked")
    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);
    }

   
    public FutureTask(Callable<V> callable) {
        if (callable == null)
            throw new NullPointerException();
        this.callable = callable;
        this.state = NEW;       // ensure visibility of callable
    }

   

    public boolean isCancelled() {
        return state >= CANCELLED;
    }

    public boolean isDone() {
        return state != NEW;
    }
   

 

   
    protected void set(V v) {
        if (STATE.compareAndSet(this, NEW, COMPLETING)) {
            outcome = v;
            STATE.setRelease(this, NORMAL); // final state
            finishCompletion();
        }
    }

  
 
    public void run() {
        if (state != NEW ||
            !RUNNER.compareAndSet(this, null, Thread.currentThread()))
            return;
        try {
            Callable<V> c = callable;
            if (c != null && state == NEW) {
                V result;
                boolean ran;
                try {
                    result = c.call();
                    ran = true;
                } catch (Throwable ex) {
                    result = null;
                    ran = false;
                    setException(ex);
                }
                if (ran)
                    set(result);
            }
        } finally {
           
            runner = null;
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }

  
    
    private static final VarHandle STATE;
    private static final VarHandle RUNNER;
    private static final VarHandle WAITERS;
    static {
        try {
            MethodHandles.Lookup l = MethodHandles.lookup();
            STATE = l.findVarHandle(FutureTask.class, "state", int.class);
            RUNNER = l.findVarHandle(FutureTask.class, "runner", Thread.class);
            WAITERS = l.findVarHandle(FutureTask.class, "waiters", WaitNode.class);
        } catch (ReflectiveOperationException e) {
            throw new ExceptionInInitializerError(e);
        }

        // Reduce the risk of rare disastrous classloading in first call to
        // LockSupport.park: https://bugs.openjdk.java.net/browse/JDK-8074773
        Class<?> ensureLoaded = LockSupport.class;
    }

}

 我们直接看run()方法,里面有一个状态state, if (state != NEW ||
            !RUNNER.compareAndSet(this, null, Thread.currentThread()))
            return;

不满足此条件会直接return,不会执行run方法。

我们的示例代码:

   

 FutureTask<String> thread = new FutureTask<>(new Demo3());//初始化,state=NEW;
        new Thread(thread,"one").start();//此时执行此线程,会进入FutureTask的run方法,执行,然后stata会被改变
        /*
        第二次同一个对象,进入FutureTask的run方法,因state被改变,直接ruturn。这样设计主要是为了         线程安全
        */
        new Thread(thread,"two").start();
发布了159 篇原创文章 · 获赞 86 · 访问量 7万+

猜你喜欢

转载自blog.csdn.net/qq_40301026/article/details/95987958