Future接口get()方法是阻塞的

    /**
     * Waits if necessary for the computation to complete, and then
     * retrieves its result.
     *
     * @return the computed result
     * @throws CancellationException if the computation was cancelled
     * @throws ExecutionException if the computation threw an
     * exception
     * @throws InterruptedException if the current thread was interrupted
     * while waiting
     */
    V get() throws InterruptedException, ExecutionException;

以上为源码,以下详细描述。

一、问题由来

  • LinkedBlockingQueue:一个基于链表实现的阻塞队列,按 FIFO 排序任务,可以设置容量(有界队列),不设置容量则默认使用Integer.Max_VALUE作为容量(无界队列)。
  • AbortPolicy拒绝策略:任务阻塞队列满了会直接抛出RejectedExecutionException异常。
public class TestThreadPool {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2
                , 5
                , 5
                , TimeUnit.SECONDS
                , new LinkedBlockingQueue<>(2)
                , new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r);
            }
        }, new ThreadPoolExecutor.AbortPolicy());

        //用有返回值的summit方法,测试拒绝策略
        for (int i = 0; i < 100; i++) {
            int a = i;
            Future<Object> future = threadPool.submit(new Callable<Object>() {
                @Override
                public Object call() throws Exception {
                    System.out.println(Thread.currentThread().getName()+".....循环次数为"+a);
                    return Thread.currentThread().getName();
                }
            });
            Object result = future.get();
            System.out.println(result);
        }
    }
}

 起初,通过summit方法来测试拒绝策略AbortPolicy,然而运行以上程序后并没有看到有异常抛出。输出结果如下:

由上面执行结果可知, 并没有看到预期的结果,只有2个线程在执行结果。而corePoolSize为2,maximumPoolSize为5,可是并没有看到5个线程;使用的指定长度为2的任务阻塞队列LinkedBlockingQueue,队列满了,应该抛出异常才对。网上查资料是这样说的:

二、验证get()的阻塞效果

将上面的代码最后两行注释掉,如下图,运行结果如下:

//        Object result = future.get();
//        System.out.println(result);

这次出现了预期的效果,看到工作线程共5个(0~4),循环次数共7次(0~6) ,其中有2次在有界阻塞队列中等待,因为拒绝策略使用的是直接抛异常的方式AbortPolicy。

也说明Future的get()方法获取结果是阻塞的,即当前线程执行结束并获取到结果后才会继续执行下个线程,这样就无法实现多线程的效果。所以,能不获取时,尽可能不获取。

三、测试有无get的结果差多少

上面的代码做几处改动:

  • 任务阻塞队列的限定长度去掉,即变为无界阻塞队列;
  • 循环体中sout语句注释掉;循环次数改为100万次;
  • 增加打印耗时的代码;
import java.util.concurrent.*;

public class TestThreadPool {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        ThreadPoolExecutor threadPool = new ThreadPoolExecutor(2
                , 5
                , 5
                , TimeUnit.SECONDS
                , new LinkedBlockingQueue<>()
                , new ThreadFactory() {
            @Override
            public Thread newThread(Runnable r) {
                return new Thread(r);
            }
        }, new ThreadPoolExecutor.AbortPolicy());

        //用有返回值的summit方法,测试拒绝策略
        long start = System.currentTimeMillis();
        for (int i = 0; i < 1_000_000; i++) {
            int a = i;
            Future<Object> future = threadPool.submit(new Callable<Object>() {
                @Override
                public Object call() throws Exception {
//                    System.out.println(Thread.currentThread().getName()+".....循环次数为"+a);
                    return Thread.currentThread().getName();
                }
            });
            Object result = future.get();
//            System.out.println(result);
        }
        long end = System.currentTimeMillis();
        System.out.println(end-start);
    }
}

当有  Object result = future.get(); 这一行时,输出结果为耗时:10509ms;

当没有  Object result = future.get(); 这一行时,输出结果为耗时:144ms;

可见,结果还是很明显的。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值