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

这篇博客探讨了FutureTask类的源码细节,尤其是其内部状态管理和执行逻辑。作者发现使用Callable接口创建的任务并未如预期那样交替执行,与Runnable的情况有所不同。文章通过示例代码说明了FutureTask在不满足特定条件时如何避免执行run方法。
摘要由CSDN通过智能技术生成

 

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();

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值