• 【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下有以下几种方式创建线程池:

    这里写图片描述

  • 相关阅读:
    FTPClient FTPFile 找不到符号
    1.4 Spring 依赖注入(DI)和控制反转(IOC)详解
    1.3使用marven Spring项目快速搭建
    1.1Spring历史发展和模块定义
    @Component、@Service、@Controller、@Rrepository说明
    打板炒股方法
    性能测试Jmeter扩展学习-添加自定义函数
    性能测试day07_性能瓶颈和分析
    性能测试day06_需求设计的学习(性能重中之重,思维方向永远重于工具)
    性能监控扩展篇(grafana + influxdb + telegraf)
  • 原文地址:https://www.cnblogs.com/cnsec/p/13286707.html
Copyright © 2020-2023  润新知