• 并发编程-concurrent指南-线程池ExecutorService的使用


    有几种不同的方式来将任务委托给 ExecutorService 去执行:

    • execute(Runnable)
    • submit(Runnable)
    • submit(Callable)
    • invokeAny(…)
    • invokeAll(…)

    execute(Runnable)

    execute(Runnable) 方法要求一个 java.lang.Runnable 对象,然后对它进行异步执行。以下是使用 ExecutorService 执行一个 Runnable 的示例:

    ExecutorService executorService = Executors.newSingleThreadExecutor();  
    
    executorService.execute(new Runnable() {  
        public void run() {  
            System.out.println("Asynchronous task");  
        }  
    });  
    
    executorService.shutdown(); 

    没有办法得知被执行的 Runnable 的执行结果。如果有需要的话你得使用一个 Callable(以下将做介绍)。

    submit(Runnable)

    submit(Runnable) 方法也要求一个 Runnable 实现类,但它返回一个 Future 对象。这个 Future 对象可以用来检查 Runnable 是否已经执行完毕。

    以下是 ExecutorService submit() 示例:

    Future future = executorService.submit(new Runnable() {  
        public void run() {  
            System.out.println("Asynchronous task");  
        }  
    });  
    
    future.get();  //returns null if the task has finished correctly.  

    submit(Callable)

    submit(Callable) 方法类似于 submit(Runnable) 方法,除了它所要求的参数类型之外。Callable 实例除了它的 call() 方法能够返回一个结果之外和一个 Runnable 很相像。Runnable.run() 不能够返回一个结果。
    Callable 的结果可以通过 submit(Callable) 方法返回的 Future 对象进行获取。以下是一个 ExecutorService Callable 示例:

    import java.util.concurrent.*;
    
    public class Main {
        public static void main(String[] args) {
            ExecutorService executorService = Executors.newSingleThreadExecutor();
    
            Future future = executorService.submit(new Runnable() {
                public void run() {
                    try {
                        TimeUnit.SECONDS.sleep(4);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("Asynchronous task");
                }
            });
            System.out.println("主方法。。。。");
            try {
                System.out.println(future.get());  //returns null if the task has finished correctly.
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }

    结果:

    主方法。。。。
    Asynchronous task
    null

    future.get()会等待子线程结束后,打印出信息。

    submit(Callable)

    submit(Callable) 方法类似于 submit(Runnable) 方法,除了它所要求的参数类型之外。Callable 实例除了它的 call() 方法能够返回一个结果之外和一个 Runnable 很相像。Runnable.run() 不能够返回一个结果。
    Callable 的结果可以通过 submit(Callable) 方法返回的 Future 对象进行获取。以下是一个 ExecutorService Callable 示例:

    import java.util.concurrent.*;
    
    public class Main {
        public static void main(String[] args) {
            ExecutorService executorService = Executors.newSingleThreadExecutor();
    
            Future future = executorService.submit(new Callable(){
                public Object call() throws Exception {
                    TimeUnit.SECONDS.sleep(3);
                    System.out.println("Asynchronous Callable");
                    return "Callable Result";
                }
            });
            System.out.println("主方法。。。。");
            try {
                System.out.println(future.get());  //returns null if the task has finished correctly.
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }

    结果:

    主方法。。。。
    Asynchronous Callable
    Callable Result

    future.get()会等待子线程结束后,打印出信息


    invokeAll()

    invokeAll() 方法将调用你在集合中传给 ExecutorService 的所有 Callable 对象。invokeAll() 返回一系列的 Future 对象,通过它们你可以获取每个 Callable 的执行结果。

    记住,一个任务可能会由于一个异常而结束,因此它可能没有 “成功”。无法通过一个 Future 对象来告知我们是两种结束中的哪一种。

    以下是一个代码示例:

    import java.util.HashSet;
    import java.util.List;
    import java.util.Set;
    import java.util.concurrent.*;
    
    public class Main {
        public static void main(String[] args) {
            ExecutorService executorService = Executors.newSingleThreadExecutor();
    
            Set<Callable<String>> callables = new HashSet<Callable<String>>();
    
            callables.add(new Callable<String>() {
                public String call() throws Exception {
                    System.out.println(Thread.currentThread().getName()+",Task 1");
                    return "Task 1";
                }
            });
            callables.add(new Callable<String>() {
                public String call() throws Exception {
                    System.out.println(Thread.currentThread().getName()+",Task 2");
                    return "Task 2";
                }
            });
            callables.add(new Callable<String>() {
                public String call() throws Exception {
                    System.out.println(Thread.currentThread().getName()+",Task 3");
                    return "Task 3";
                }
            });
            callables.add(new Callable<String>() {
                public String call() throws Exception {
                    System.out.println(Thread.currentThread().getName()+",Task 4");
                    return "Task 4";
                }
            });
            callables.add(new Callable<String>() {
                public String call() throws Exception {
                    System.out.println(Thread.currentThread().getName()+",Task 5");
                    return "Task 5";
                }
            });
    
            try {
                List<Future<String>> futures  = executorService.invokeAll(callables);
                for(Future<String> future : futures){
                    System.out.println("future.get = " + future.get());
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
            executorService.shutdown();
        }
    }

    结果:

    pool-1-thread-1,Task 2
    pool-1-thread-1,Task 5
    pool-1-thread-1,Task 4
    pool-1-thread-1,Task 1
    pool-1-thread-1,Task 3
    future.get = Task 2
    future.get = Task 5
    future.get = Task 4
    future.get = Task 1
    future.get = Task 3

    ExecutorService 关闭

    使用完 ExecutorService 之后你应该将其关闭,以使其中的线程不再运行。

    比如,如果你的应用是通过一个 main() 方法启动的,之后 main 方法退出了你的应用,如果你的应用有一个活动的 ExexutorService 它将还会保持运行。ExecutorService 里的活动线程阻止了 JVM 的关闭。

    要终止 ExecutorService 里的线程你需要调用 ExecutorService 的 shutdown() 方法。ExecutorService 并不会立即关闭,但它将不再接受新的任务,而且一旦所有线程都完成了当前任务的时候,ExecutorService 将会关闭。在 shutdown() 被调用之前所有提交给 ExecutorService 的任务都被执行

    如果你想要立即关闭 ExecutorService,你可以调用 shutdownNow() 方法。这样会立即尝试停止所有执行中的任务,并忽略掉那些已提交但尚未开始处理的任务。无法担保执行任务的正确执行。可能它们被停止了,也可能已经执行结束。




  • 相关阅读:
    Python Day 24 类属性与对象属性、初始化方法init、绑定方法与非绑定方法、OOP三大特性之继承、抽象与继承、存在继承关系后的属性查找、派生与覆盖、子类中重用父类的方法
    Python Day 23 xml模块 、面向对象
    Python Day 22 configparser模块、subprocess模块、xlrd模块、xlwt模块
    LeetCode 两个数之和
    python ATM + 购物车
    python Day 19 random、json、pickle、hashlib、hmac、shutil、shelve
    Python Day 18 time模块、datetime模块、os模块、os.path模块
    解释型语言和编译型语言的区别
    GCC和G++区别
    安装python+setuptools+pip+nltk
  • 原文地址:https://www.cnblogs.com/qjm201000/p/10156491.html
Copyright © 2020-2023  润新知