java线程中Future

如果在执行线程时,想得到线程的返回值可以使用Future。如果只是一个线程,那么没有必要使用。

Callable:这个接口声明了call()方法。可以再这个方法里实现任务的具体逻辑操作。Callable接口是一个泛型接口,这就意味着必须声明call()方法返回的数据类型。

Future:这个接口声明了一些方法来获取Callbale对象产生的结果,并管理他们的状态。

FutureTask:这个类提供了一个名为done()的方法,允许在执行器中的任务执行结束后 ,还可以执行一些代码。

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
public class SFuture {

    public static void main(String[] args) throws Exception{
        
        ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
        //这里调用submit 方法,并且有一个future返回值
        Future<String> future = newSingleThreadExecutor.submit(new SCallable());
        //会等到线程执行,并且得到结果,如果线程没有执行完 ,那么会一直阻塞
        System.out.println("main线程开始执行");
        String result = future.get();
        System.out.println(result);
        System.out.println("main线程执行完毕");
        newSingleThreadExecutor.shutdown();
        
    }
    
}


class SCallable implements Callable<String>{

    @Override
    public String call() throws Exception {
        TimeUnit.SECONDS.sleep(3);
        return "call 被执行";
      
    }

    
}
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;

public class SFutureTask extends FutureTask<String>{

 
    public SFutureTask(Callable<String> callable) {
        super(callable);
       
    }
    
    @Override
    protected void done() {
        // TODO Auto-generated method stub
        try {
            TimeUnit.SECONDS.sleep(3);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        System.out.println("done方法执行完毕");
    }
    
    public static void main(String[] args) throws Exception{
        ExecutorService newSingleThreadExecutor = Executors.newSingleThreadExecutor();
        //如果使用了  FutureTask 在得到结果时 ,使用Future ,那么会返回空 ,
        /**输出结果如下:
         * main开始执行
           done方法执行完毕
                             得到结果null
           main执行完毕
         */
        /*  Future<?> submit = newSingleThreadExecutor.submit(new SFutureTask(new STCallable()));
        System.out.println("main开始执行");
        Object result = submit.get();
        System.out.println("得到结果:"+result);
        System.out.println("main执行完毕");*/
        
        SFutureTask sFutureTask = new SFutureTask(new STCallable());
        newSingleThreadExecutor.submit(sFutureTask);
        System.out.println("main开始执行");
        //如果没有结果 会一直阻塞,当结果出来 线程就会恢复
        String result = sFutureTask.get();
        System.out.println("得到结果:"+result);
        System.out.println("main执行完毕");
        newSingleThreadExecutor.shutdown();
        
        
    }
    

}

class STCallable implements Callable<String>{

    @Override
    public String call() throws Exception {
        // TODO Auto-generated method stub
        TimeUnit.SECONDS.sleep(3);
        System.out.println("进入了call方法");
        return "call  被执行";
    }
    
}

输出结果:

main开始执行
进入了call方法
得到结果:call  被执行
main执行完毕
done方法执行完毕

  private void finishCompletion() {
        // assert state > COMPLETING;
        for (WaitNode q; (q = waiters) != null;) {
            if (UNSAFE.compareAndSwapObject(this, waitersOffset, q, null)) {
                for (;;) {
                    Thread t = q.thread;
                    if (t != null) {
                        q.thread = null;
                        //唤醒线程
                        LockSupport.unpark(t);
                    }
                    WaitNode next = q.next;
                    if (next == null)
                        break;
                    q.next = null; // unlink to help gc
                    q = next;
                }
                break;
            }
        }
        //执行done方法
        done();

        callable = null;        // to reduce footprint
    }

done()因为延迟了三秒 所以最后被执行出来,从上面的代码可以看出 会唤醒线程,然后执行done方法,主线程并不需要等待done()方法执行完再执行。

 

  public void run() {
        if (state != NEW ||
            !UNSAFE.compareAndSwapObject(this, runnerOffset,
                                         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;
                    //这里面会调用finishCompletion方法
                    setException(ex);
                }
                if (ran)
                   //这里会调用finishCompletion()方法
                    set(result);
            }
        } finally {
            // runner must be non-null until state is settled to
            // prevent concurrent calls to run()
            runner = null;
            // state must be re-read after nulling runner to prevent
            // leaked interrupts
            int s = state;
            if (s >= INTERRUPTING)
                handlePossibleCancellationInterrupt(s);
        }
    }

  newSingleThreadExecutor.invokeAll(tasks):可以一次运行对个任务,当然也会返回多个结果。

newSingleThreadExecutor.invokeAny(list);可以一次执行多个结果,单只返回其中一个结果,执行顺序按照集合的顺序执行,返回值和线程池的数量也有关系,如果线程池数量为1,那么会返回第一个执行完毕并且不抛出异常的值,如果是多个线程,就会根据任务执行的时间长短,哪一个执行快,哪一个就先返回。

 private <T> T doInvokeAny(Collection<? extends Callable<T>> tasks,
                              boolean timed, long nanos)
        throws InterruptedException, ExecutionException, TimeoutException {
        if (tasks == null)
            throw new NullPointerException();
        int ntasks = tasks.size();
        if (ntasks == 0)
            throw new IllegalArgumentException();
        ArrayList<Future<T>> futures = new ArrayList<Future<T>>(ntasks);
        ExecutorCompletionService<T> ecs =
            new ExecutorCompletionService<T>(this);

        // For efficiency, especially in executors with limited
        // parallelism, check to see if previously submitted tasks are
        // done before submitting more of them. This interleaving
        // plus the exception mechanics account for messiness of main
        // loop.

        try {
            // Record exceptions so that if we fail to obtain any
            // result, we can throw the last exception we got.
            ExecutionException ee = null;
            final long deadline = timed ? System.nanoTime() + nanos : 0L;
            Iterator<? extends Callable<T>> it = tasks.iterator();

            // Start one task for sure; the rest incrementally
           //添加第一个任务
            futures.add(ecs.submit(it.next()));
            --ntasks;
            int active = 1;

            for (;;) {
                //判断是否有值返回
                Future<T> f = ecs.poll();
                if (f == null) {
                    if (ntasks > 0) {
                        --ntasks;
                        //如果取不到值,就继续添加任务执行
                        futures.add(ecs.submit(it.next()));
                        ++active;
                    }
                    else if (active == 0)
                        break;
                    else if (timed) {
                        f = ecs.poll(nanos, TimeUnit.NANOSECONDS);
                        if (f == null)
                            throw new TimeoutException();
                        nanos = deadline - System.nanoTime();
                    }
                    else
                        f = ecs.take();
                }
                if (f != null) {
                    --active;
                    try {
                        return f.get();
                    } catch (ExecutionException eex) {
                        ee = eex;
                    } catch (RuntimeException rex) {
                        ee = new ExecutionException(rex);
                    }
                }
            }

            if (ee == null)
                ee = new ExecutionException();
            throw ee;

        } finally {
            for (int i = 0, size = futures.size(); i < size; i++)
                futures.get(i).cancel(true);
        }
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值