线程池方式开启线程--submit()和execute()的区别

本文详细介绍了如何使用Java线程池执行有返回值和无返回值的任务,通过示例代码展示了submit()和execute()的区别。submit()方法能处理Callable和Runnable任务,异常会被捕获,可以通过Future获取结果;execute()仅接受Runnable任务,异常会直接抛出。在实际应用中,根据需求选择合适的方法。
摘要由CSDN通过智能技术生成

目录

1. 线程池方式开启线程

1.1 创建线程池,并开启有返回值的线程的代码

1.2 创建线程池,并开启无返回值的线程

2. submit()和execute()提交任务的区别

2.1 submit代码展示

 2.1.2 submit提交任务,异常被吃,通过Future的get方法将任务执行时的异常重新抛出

 2.2 execute代码展示

 2.2.1 execute提交的线程可以通过FutureTask获取线程结果

没有引用线程池的时候,需要我们通过继承Thread类和实现Runnable、Callable接口,最终调用start()方法启动线程。

想要理解线程和线程池介绍,可以学习下这篇博客:多线程--线程和线程池的用法_傻鱼爱编程的博客-CSDN博客

现在我们可以通过线程池的execute()和submit()方法来提交线程任务。

1. 线程池方式开启线程

提交的任务可以选择是否需要返回值:

1.1 创建线程池,并开启有返回值的线程的代码

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        int inter = 6;
        System.out.println("电脑核心线程数 = " + Runtime.getRuntime().availableProcessors());
        // 创建线程池(自定义参数)
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
                6,
                10,
                10L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(10),
                new CustomizableThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy());

        // 定义线程数组(也可以用线程集合)
        FutureTask[] futureTask = new FutureTask[inter];
        // 开启6个线程
        for (int i = 0; i < inter; i++) {
            futureTask[i] = new FutureTask<>(new Callable<String>() {
                @Override
                public String call() throws Exception {
                    // 模拟程序执行时间1S
                    Thread.sleep(1000);
                    System.out.println("线程数量activeCount = " + poolExecutor.getActiveCount());
                    System.out.println("排队数量size = " + poolExecutor.getQueue().size());
                    return "Callable在线程池中执行了。。" + Thread.currentThread().getName();
                }
            });
            // 线程池开启线程
            poolExecutor.submit(futureTask[i]);
        }
        // 获取线程的执行结果
        for (FutureTask task : futureTask) {
            System.out.println("task返回结果 = " + task.get());
        }
        // 关闭线程池(现实项目中不关线程池)
        poolExecutor.shutdown();
    }

1.2 创建线程池,并开启无返回值的线程

public static void main(String[] args) {
        int inter = 6;
        System.out.println("电脑核心线程数 = " + Runtime.getRuntime().availableProcessors());
        // 创建线程池(自定义参数)
        ThreadPoolExecutor poolExecutor = new ThreadPoolExecutor(
                5,
                10,
                10L,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(10),
                new CustomizableThreadFactory(),
                new ThreadPoolExecutor.CallerRunsPolicy());

        // 定义线程数组(也可以用线程集合)
        Runnable[] runnables = new Runnable[inter];
        // 开启6个线程
        for (int i = 0; i < inter; i++) {
            runnables[i] = new Runnable() {
                @Override
                public void run() {
                    // 模拟程序执行
                    System.out.println("添加需要运行的程序===");
                    System.out.println("线程池线程总数量 = " + poolExecutor.getPoolSize());
                    System.out.println("线程数量activeCount = " + poolExecutor.getActiveCount());
                    System.out.println("排队数量size = " + poolExecutor.getQueue().size());
                }
            };
            // 线程池开启线程
            poolExecutor.submit(runnables[i]);
        }
        // 关闭线程池(现实项目中不关线程池)
        poolExecutor.shutdown();
    }

2. submit()和execute()提交任务的区别

submit()execute()
提交任务的类型既能提交Runnable类型任务也能提交Callable类型任务只能提交Runnable类型的任务()
异常的处理方式会吃掉异常。可通过Future的get方法将任务执行时的异常重新抛出

会直接抛出任务执行时的异常

是否有返回值

有返回值,需要返回值的时候可以使用submit

execute()没有返回值,可通过Future的get方法获取返回值

2.1 submit代码展示

源码展示(可以提交Callable类型和Runable类型):

2.1.1 submit提交任务,异常被吃的情况

    public static void main(String[] args) {
        int inter = 3;
        // 创建线程池(自定义参数)
        ExecutorService executorService = Executors.newFixedThreadPool(3);

        // 定义线程数组(也可以用线程集合)
        Callable[] callables = new Callable[inter];
        // 开启6个线程
        for (int i = 0; i < inter; i++) {
            callables[i] = new Callable<String>(){
                @Override
                public String call() throws Exception {
                    System.out.println("添加需要运行的程序===");
                    Thread.sleep(10*1000);
                    // 手动添加一个异常
                    int aa =1/0;
                    return "程序运行成功";
                }
            };
            // 线程池开启线程
            executorService.submit(callables[i]);
        }
        // 关闭线程池(现实项目中不关线程池)
        executorService.shutdown();
    }

控制台打印结果:无异常抛出

 2.1.2 submit提交任务,异常被吃,通过Future的get方法将任务执行时的异常重新抛出

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        int inter = 3;
        // 创建线程池(自定义参数)
        ExecutorService executorService = Executors.newFixedThreadPool(3);

        // 定义线程数组(也可以用线程集合)
        Callable[] callables = new Callable[inter];
        ArrayList<Future> futureTasks = new ArrayList<>();
        // 开启6个线程
        for (int i = 0; i < inter; i++) {
            callables[i] = new Callable<String>(){
                @Override
                public String call() throws Exception {
                    System.out.println("添加需要运行的程序===");
                    Thread.sleep(10*1000);
                    // 手动添加一个异常
                    int aa =1/0;
                    return "程序运行成功";
                }
            };
            // 线程池开启线程
            Future submit = executorService.submit(callables[i]);
            futureTasks.add(submit);
        }
        // 获取线程结果
        for (Future futureTask : futureTasks) {
            System.out.println("返回结果 = " + futureTask.get());
        }
        // 关闭线程池(现实项目中不关线程池)
        executorService.shutdown();
    }

控制台打印:异常被抛出

 2.2 execute代码展示

源码展示(只能提交Runable类型):

 2.2.1 execute提交的线程可以通过FutureTask获取线程结果

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        int inter = 3;
        // 创建线程池(自定义参数)
        ExecutorService executorService = Executors.newFixedThreadPool(3);

        // 定义线程数组(也可以用线程集合)
        FutureTask[] integerFuture = new FutureTask[inter];
        // 开启6个线程
        for (int i = 0; i < inter; i++) {
            integerFuture[i] = new FutureTask<>(new Callable<Object>() {
                @Override
                public Object call() throws Exception {
                    System.out.println("添加需要运行的程序===");
                    Thread.sleep(10*1000);
                    return "程序返回的结果";
                }
            });
            // 线程池开启线程
            executorService.execute(integerFuture[i]);
        }
        // 通过FutureTask获取结果
        for (FutureTask futureTask : integerFuture) {
            System.out.println("获取的线程结果:" + futureTask.get());
        }
        // 关闭线程池(现实项目中不关线程池)
        executorService.shutdown();
    }

总结:通过submit()和execute()源码可以看出submit封装了execute,如果没有特殊情况应该优先选择execute。因为execute效率会更高,异常也不会被吃掉。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值