【Java并发】Executor笔记

Executor

基于生产者-消费者模式,用于异步处理线程(提交、执行等)。

Executor里有一个excute(Runnable)方法,用于执行线程。

ExecutorService

ExecutorService继承于Executor,也是一个接口,它主要有以下方法:

    execute(Runnable)//执行Runnable

submit(Runnable)//提交Runnable

submit(Callable)//提交Callable,会返回一个Future对象,可以后去线程执行的返回值。

invokeAny(...)//参数是Callable的集合,不会返回一个Future对象,而是返回集合中某个线程执行后的值,具体是哪一个线程返回的是不确定的。但是返回值了说明所有线程都执行成功了。

invokeAll(...)//参数是Callable的集合,会返回一个List<Future>,存储每个线程的返回值。

execute

    ExecutorService executorService = Executors.newFixedThreadPool(3);

创建了一个线程池,大小为3,也就是一次可以异步执行3个线程,
然后调用execute()来执行这些线程。

    public class Test6 {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(3);
        executorService.execute(new Th6("th1"));
        executorService.execute(new Th6("th2"));
        executorService.execute(new Th6("th3"));
        executorService.execute(new Th6("th4"));
        executorService.execute(new Th6("th5"));
    }
    }
    class Th6 implements Runnable{
    private int a;
    private String name ;
    public Th6(String name){
        this.name = name;
    }
    @Override
    public void run() {
        while (a<2){
            System.out.println(name+" : "+(a++));
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
    }

输出结果如下:

    th1 : 0
    th2 : 0
    th3 : 0
    th1 : 1
    th2 : 1
    th3 : 1
    th4 : 0
    th5 : 0
    th5 : 1
    th4 : 1

可以看到一次只能执行3个线程,先执行了前3个线程,执行完后再执行后两个线程。

submit

对于submit(Runnable)和execute(Runnable)的效果是相似的,不在测试。

下面是传入参数为Callbale时的测试:

        public class Test6 {
        public static void main(String[] args) {
            ExecutorService executorService = Executors.newFixedThreadPool(3);
            Future<String> future =  executorService.submit(new ThC("th7"));
            try {
                System.out.println(future.get());//获取返回值
                System.out.println(future.isCancelled());//任务是否取消
                System.out.println(future.cancel(false));//取消任务(放在这里好像没意义)
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
    class ThC implements Callable<String>{
        private String name ;
        public ThC(String name){
            this.name = name;
        }
        @Override
        public String call() throws Exception {
            System.out.println(name);
            return "hello Callable";
        }
    }

输出如下:

    th7
    hello Callable
    false
    false

invokeAny

传入参数是Callable的集合,返回的是其中某个线程直线后的返回值,但是不确定是哪一个。

        public class Test6 {
        public static void main(String[] args) {
            ExecutorService executorService = Executors.newFixedThreadPool(3);
            List<Callable<String>> list = new ArrayList<>();
            list.add(new ThC("Callable1"));
            list.add(new ThC2("Callable2"));
            try {
                System.out.println(executorService.invokeAny(list));
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }

        }
    }

    class ThC implements Callable<String>{
        private String name ;
        public ThC(String name){
            this.name = name;
        }
        @Override
        public String call() throws Exception {
            System.out.println(name);
            return "hello Callable1";
        }
    }
    class ThC2 implements Callable<String>{
        private String name ;
        public ThC2(String name){
            this.name = name;
        }
        @Override
        public String call() throws Exception {
            System.out.println(name);
            return "hello Callable2";
        }
    }

输出结果:

有时候是:

    Callable1
    Callable2
    hello Callable1

有时候是:

这也说明了返回的值不确定是哪一个下线程的。

    Callable1
    Callable2
    hello Callable2

invokeAll

        public class Test6 {
        public static void main(String[] args) {
            ExecutorService executorService = Executors.newFixedThreadPool(3);
            List<Callable<String>> list = new ArrayList<>();
            list.add(new ThC("Callable1"));
            list.add(new ThC2("Callable2"));
            try {
                for (Future<String> future : executorService.invokeAll(list)){
                    System.out.println(future.get());
                }

            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }

        }
    }

    class ThC implements Callable<String>{
        private String name ;
        public ThC(String name){
            this.name = name;
        }
        @Override
        public String call() throws Exception {
            Thread.sleep(1000);
            System.out.println(name);
            return "hello Callable1";
        }
    }
    class ThC2 implements Callable<String>{
        private String name ;
        public ThC2(String name){
            this.name = name;
        }
        @Override
        public String call() throws Exception {
            System.out.println(name);
            return "hello Callable2";
        }
    }

输出结果:

    Callable2
    Callable1
    hello Callable1
    hello Callable2

上边代码中在ThC线程中加延时了1秒执行,目的是为了测试返回Future对象集合的顺序性,由输出顺序可以看到,返回的Future对象集合的顺序是原Callable集合中的顺序,也就是说Executor的invokeAll方法是在所有Callable集合线程执行完之后才返回的,并且保证了返回的顺序性。

线程池

Executors下有以下几种方式创建线程池:

这里写图片描述

原文地址:https://www.cnblogs.com/cnsec/p/13286707.html