线程池submit的坑

package com.middle.threadpool;

import java.util.concurrent.*;

/**
 * @author 15510
 * @create 2019-07-31 20:39
 */
public class ThreadPoolDemo {
    public static void main(String[] args) {

        ExecutorService executorService = Executors.newFixedThreadPool(4);

        for (int i = 0; i < 5; i++) {
            int index = i;
            executorService.submit(() -> divTask(100, index));
        }
        executorService.shutdown();
    }

    private static void divTask(int a, int b) {
        double result = a / b;
        System.out.println(result);
    }

}

结果如下

100.0
33.0
50.0
25.0

Process finished with exit code 0

上述代码,可以看出运行结果为4个,应该是有5个的,但是当 i=0 的时候,100/0是会报错的,但是日志信息中没有任何信息,是为什么那?如果使用了 submit(Runnable task) 就会出现这种情况,任何的错误信息都出现不了!


这是因为使用 submit(Runnable task) 的时候,错误的堆栈信息跑出来的时候会被内部捕获到,所以打印不出来具体的信息让我们查看,解决的方法有如下两种:

  1. 使用 execute() 代替 submit()
package com.middle.threadpool;

import java.util.concurrent.*;

/**
 * @author 15510
 * @create 2019-07-31 20:39
 */
public class ThreadPoolDemo {
    public static void main(String[] args) {

        ExecutorService executorService = Executors.newFixedThreadPool(4);

        for (int i = 0; i < 5; i++) {
            int index = i;
            executorService.execute(() -> divTask(100, index));
        }
        executorService.shutdown();
    }

    private static void divTask(int a, int b) {
        double result = a / b;
        System.out.println(result);
    }

}

结果

Exception in thread "pool-1-thread-1" 100.0
25.0
33.0
50.0
java.lang.ArithmeticException: / by zero
	at com.middle.threadpool.ThreadPoolDemo.divTask(ThreadPoolDemo.java:22)
	at com.middle.threadpool.ThreadPoolDemo.lambda$main$0(ThreadPoolDemo.java:16)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)

Process finished with exit code 0
  1. 使用Future
package com.middle.threadpool;

import java.util.concurrent.*;

/**
 * @author 15510
 * @create 2019-07-31 20:39
 */
public class ThreadPoolDemo {
    public static void main(String[] args) {

        ExecutorService executorService = Executors.newFixedThreadPool(4);

        for (int i = 0; i < 5; i++) {
            int index = i;
            Future<?> future = executorService.submit(() -> divTask(100, index));

            try {
                future.get();
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }
        executorService.shutdown();
    }

    private static void divTask(int a, int b) {
        double result = a / b;
        System.out.println(result);
    }

}

结果

java.util.concurrent.ExecutionException: java.lang.ArithmeticException: / by zero
	at java.util.concurrent.FutureTask.report(FutureTask.java:122)
	at java.util.concurrent.FutureTask.get(FutureTask.java:192)
	at com.middle.threadpool.ThreadPoolDemo.main(ThreadPoolDemo.java:19)
Caused by: java.lang.ArithmeticException: / by zero
	at com.middle.threadpool.ThreadPoolDemo.divTask(ThreadPoolDemo.java:28)
	at com.middle.threadpool.ThreadPoolDemo.lambda$main$0(ThreadPoolDemo.java:16)
	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
100.0
50.0
33.0
25.0

Process finished with exit code 0
  1. execute 和 submit 的区别

execute() 方法用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功。

submit() 方法用于提交需要返回值的任务。线程池会返回一个 future 类型的对象,通过这个 future 对象可以判断任务是否执行成功,并且可以通过 future 的 get() 方法来获取返回值,get() 方法会阻塞当前线程直到任务完成,而使用 get(long timeout,TimeUnit unit)方法则会阻塞当前线程一段时间后立即返回,这时候有可能任务没有执行完。
没有返回值也是可以用submit

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值