• Java并发:搞定线程池(中)


    向线程池提交任务

    1.1 execute()

        用于提交不需要返回值的任务,所以无法判断任务是否被线程池执行成功。输入的是一个Runnable实例。

    public void execute(Runnable command) { e.execute(command); }

        如果没有特殊要求,使用缓存线程池是最合适的;

        如果只能运行一个线程,就使用单线程池;

        如果运行调度任务,则按需使用调度线程池或单线程池;

        如果没有其他特殊要求,可以直接使用ThreadPoolExecutor类的构造函数来创建线程池,并自己给定7个参数。

    public static void main(String[] args) throws ExecutionException, InterruptedException {
            ExecutorService executorService = Executors.newFixedThreadPool(3);
            List<Future<String>> list = new ArrayList<>();
            for (int i = 0; i < 100; i++) {
                //任务放到阻塞队列
                executorService.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            TimeUnit.SECONDS.sleep(2);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                        System.out.println(Thread.currentThread().getName());
                    }
                });
            }
    

      

    1.2 submit()

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

    public static void main(String[] args) throws ExecutionException, InterruptedException {
            ExecutorService executorService = Executors.newFixedThreadPool(3);
            List<Future<String>> list = new ArrayList<>();
            for (int i = 0; i < 100; i++) {
                //任务放到阻塞队列
                Future<String> f = executorService.submit(new Callable<String>() {
                    @Override
                    public String call() throws Exception {
                        TimeUnit.SECONDS.sleep(2);
                        return Thread.currentThread().getName();
                    }
                });
                list.add(f);
            }
            for(int i=0;i<list.size();i++){
                System.out.println(list.get(i).get()+"--------------"+i+"-------------------------");
            }
        }

    关闭线程池

        通过调用线程池的shutdown或shutdownNow方法来关闭线程池。

        他们两个原理是遍历线程池中的工作线程,然后逐个调用线程的interrupt方法来终端线程,所以无法响应终端的任务可能永远无法终止。

        shutdownNow:首先将线程池的状态设置成stop,然后尝试停止所有的正在执行或暂停任务的线程,并返回等待执行的任务的列表。

        shutdown:只是将线程池的状态设置成shutdown状态,然后中段所有没有正在执行任务的线程。

        只要调用者两个关闭方法中的任意一个,isShutdown方法就会返回true,当所有的任务关闭后,才表示线程池瓜女子成功,这是调用isTerminaed方法会返回true。

        通常shutdown方法来关闭线程池,若任务不一定执行完,则可以调用shutdownNow方法。

        使用有界队列,可以增加系统的稳定性和预警能力。

    线程池的状态

        1. 当线程池创建后,初始为running状态

        2. 调用shutdown方法后,处于shutdown状态,此事不再接受新的任务,等待已有的任务执行完毕

        3. 执行shutdownNow方法后,进入stop状态,不在接受新的任务,并且尝试终止正在执行的任务

        4. 当处于shutdown或stop状态,并且所有的工作线程已经销毁,任务缓存队列已经清空,线程池被设为terminated状态。

         * Possible state transitions:
         * NEW -> COMPLETING -> NORMAL
         * NEW -> COMPLETING -> EXCEPTIONAL
         * NEW -> CANCELLED
         * NEW -> INTERRUPTING -> INTERRUPTED
    
        private static final int NEW          = 0;
        private static final int COMPLETING   = 1;
        private static final int NORMAL       = 2;
        private static final int EXCEPTIONAL  = 3;
        private static final int CANCELLED    = 4;
        private static final int INTERRUPTING = 5;
        private static final int INTERRUPTED  = 6;
    

      

  • 相关阅读:
    HDU1074 Doing Homework(状压dp)
    HDU1069 Monkey and Banana(dp)
    HDU1024 Max Sum Plus Plus(dp)
    codeforces 1288E. Messenger Simulator(树状数组)
    codeforces 1288D. Minimax Problem(二分)
    geotrellis使用(三十二)大量GeoTiff文件实时发布TMS服务
    geotrellis使用(三十一)使用geotrellis直接将GeoTiff发布为TMS服务
    OpenStack(企业私有云)万里长征第六步——OpenStack网络及虚拟机存储位置
    geotrellis使用(三十)使用geotrellis读取PostGIS空间数据
    Docker Swarm——集群管理
  • 原文地址:https://www.cnblogs.com/dc-earl/p/11126825.html
Copyright © 2020-2023  润新知