zoukankan      html  css  js  c++  java
  • 线程池

      我们之前使用线程的时候就去创建一个线程,这样实现起来非常简便,但是就会有一个问题:如果并发的线程数量很多,并且每个线程都是执行一个时间很短的任务就结束了,这样频繁创建线程就会大大降低系统的效率,因为频繁创建线程和销毁线程需要时间。

      假设一个服务器完成一项任务所需时间为:T1 创建线程时间,T2 在线程中执行任务的时间,T3 销毁线程时间。

      如果:T1 + T3 远大于 T2,则可以采用线程池,以提高服务器性能。

      多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力。

      java类库中提供的线程池简介:

      java.util.concurrent包提供了现成的线程池的实现。

      Executor是一个顶层接口,在它里面只声明了一个方法execute(Runnable),返回值为void,参数为Runnable类型,从字面意思可以理解,就是用来执行传进去的任务的;

      然后ExecutorService接口继承了Executor接口,并声明了一些方法:submit、invokeAll、invokeAny以及shutDown等;

      抽象类AbstractExecutorService实现了ExecutorService接口,基本实现了ExecutorService中声明的所有方法;

      然后ThreadPoolExecutor继承了类AbstractExecutorService。

      在ThreadPoolExecutor类中有几个非常重要的方法:

    execute()
    submit()
    shutdown()
    shutdownNow()

      execute()方法实际上是Executor中声明的方法,在ThreadPoolExecutor进行了具体的实现,这个方法是ThreadPoolExecutor的核心方法,通过这个方法可以向线程池提交一个任务,交由线程池去执行。

      submit()方法是在ExecutorService中声明的方法,在AbstractExecutorService就已经有了具体的实现,在ThreadPoolExecutor中并没有对其进行重写,这个方法也是用来向线程池提交任务的,但是它和execute()方法不同,它能够返回任务执行的结果,去看submit()方法的实现,会发现它实际上还是调用的execute()方法,只不过它利用了Future来获取任务执行结果

      shutdown()和shutdownNow()是用来关闭线程池的。

      不过在java doc中,并不提倡我们直接使用ThreadPoolExecutor,而是使用Executors类中提供的几个静态方法来创建线程池:

    package pool;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    /**
     * newCachedThreadPool()
     * 线程池为无限大,当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
     * 有任务才会创建线程,空闲线程会被保留60s
     */
    public class ThreadPoolExecutorTest1 {
        
        public static void main(String[] args) {
            ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
            for (int i = 0; i < 10; i++) {
                final int index = i;
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                cachedThreadPool.execute(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println(index);
                        System.out.println(Thread.currentThread().getName());
                    }
                });
            }
            cachedThreadPool.shutdown();// 任务执行完毕,关闭线程池
        }
    
    }
    package pool;
    
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    /**
     * newFixedThreadPool(int nThreads)
     * 创建一个定长线程池,可控制线程最大并发数,超出的线程会在队列中等待。
     * 线程池中包含固定数目的线程,空闲线程会一直保留,参数nThreads表示设定线程池中线程的数目
     *
     */
    public class ThreadPoolExecutorTest2 {
        
        public static void main(String[] args) {
            ExecutorService fixedThreadPool = Executors.newFixedThreadPool(2);
            for (int i = 0; i < 10; i++) {
                final int index = i;
                fixedThreadPool.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            System.out.println(index);
                            System.out.println(Thread.currentThread().getName());
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
            fixedThreadPool.shutdown();// 任务执行完毕,关闭线程池
        }
    
    }
    package pool;
    
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    /**
     * newScheduledThreadPool(int corePoolSize)
     * 线程池能按时间计划来执行任务,允许用户设定计划执行任务的时间。
     * 参数corePoolSize设定线程池中线程最小数目,当任务较多时,线程池可能会创建更多的工作线程来执行任务。
     *
     */
    public class ThreadPoolExecutorTest3 {
        
        public static void main(String[] args) {
            
            method1();
            //method2();
            
        }
        
        /**
         * 延迟3s执行
         */
        private static void method1(){
            System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
            scheduledThreadPool.schedule(new Runnable() {
                public void run() {
                    System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                    System.out.println("延迟2s执行");
                }
            }, 2, TimeUnit.SECONDS);
            scheduledThreadPool.shutdown();
        }
        
        /**
         * 延迟2s执行后每3s执行一次
         */
        private static void method2() {
            System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(3);
            scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
                public void run() {
                    System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                    System.out.println("延迟2s执行后每3s执行一次");
                    System.out.println(Thread.currentThread().getName());
                }
            }, 2, 3, TimeUnit.SECONDS);
        }
    
    }
    package pool;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    /**
     * newSingleThreadExecutor(int nThreads)
     * 线程池中只有一个线程,它依次执行每个任务。
     * 创建一个单线程化的线程池,它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序(FIFO, LIFO, 优先级)执行。
     *
     */
    public class ThreadPoolExecutorTest4 {
        
        public static void main(String[] args) {
            ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
            for (int i = 0; i < 10; i++) {
                final int index = i;
                singleThreadPool.execute(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            System.out.println(index);
                            System.out.println(Thread.currentThread().getName());
                            Thread.sleep(2000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }
            singleThreadPool.shutdown();
        }
    
    }
    package pool;
    
    
    import java.text.SimpleDateFormat;
    import java.util.Date;
    import java.util.concurrent.Executors;
    import java.util.concurrent.ScheduledExecutorService;
    import java.util.concurrent.TimeUnit;
    /**
     * newSingleThreadScheduledExecutor()
     * 线程池中只有一个线程,它能按照时间计划执行每个任务。
     *
     */
    public class ThreadPoolExecutorTest5 {
        
        public static void main(String[] args) {
            
            //method1();
            method2();
            
        }
        
        /**
         * 延迟3s执行
         */
        private static void method1(){
            System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            ScheduledExecutorService scheduledThreadPool = Executors.newSingleThreadScheduledExecutor();
            scheduledThreadPool.schedule(new Runnable() {
                public void run() {
                    System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                    System.out.println("延迟2s执行");
                }
            }, 2, TimeUnit.SECONDS);
        }
        
        /**
         * 延迟2s执行后每3s执行一次
         */
        private static void method2() {
            System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
            ScheduledExecutorService scheduledThreadPool = Executors.newSingleThreadScheduledExecutor();
            scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
                public void run() {
                    System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date()));
                    System.out.println("延迟2s执行后每3s执行一次");
                    System.out.println(Thread.currentThread().getName());
                }
            }, 2, 3, TimeUnit.SECONDS);
        }
    
    }

    转自:http://www.cnblogs.com/wbyp/p/7682680.html

  • 相关阅读:
    《梦断代码》读书笔记(二)
    周总结(十三)
    周总结(十)
    知识圈APP开发记录(十六)
    《梦断代码》读书笔记(一)
    知识圈APP开发记录(十五)
    朴素贝叶斯
    单源最短路径 djkstra
    有向图 拓扑排序 文件依赖下的编译顺序该如何确定?
    《人类简史》读后感
  • 原文地址:https://www.cnblogs.com/rookie-newbie/p/8086065.html
Copyright © 2011-2022 走看看