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

    服务器应用程序经常需要处理执行时间很短而数目巨大的请求, 如果为每一个请求创建一个新的线程, 会导致一些问题的出现, 如:

    1. 性能瓶颈. 线程的创建和销毁需要执行大量的后台操作, 如果单个请求的执行时间很短, 有可能花在创建和销毁线程上的时间大于真正执行请求的时间.

    2. 可能会导致资源不足. 大量的并发请求意味着需要创建大量的线程, 过多的线程存在会吞噬大量的系统资源, 而且CPU需要在这些线程间不断切换, 这可能引发"切换过度"的问题.

    为了适应上述场合, java在JDK1.5中引入了线程池的概念. 线程池中存放着一定数量的已创建好的线程, 当一个请求到来时, 只需从线程池中取出一个线程来执行请求, 请求完成后再将线程归还给线程池. 同时, 我们可以为线程池指定最大的线程数量, 当池中所有线程都处于活动状态下, 新的任务会排队等候, 直到之前的某个任务处理完成后, 新的任务才能得到处理.  

     

    创建线程池. java.util.concurrent.Executors类提供了多个静态方法用于创建线程池.

    public static ExecutorService newFixedThreadPool(int nThreads): 创建一个可重用的固定线程数的线程池. 如果池中所有的nThreads个线程都处于活动状态时提交任务(任务通常是Runnable或Callable对象), 任务将在队列中等待, 直到池中出现可用线程.

    public static ExecutorService newCachedThreadPool(): 调用此方法创建的线程池可根据需要自动调整池中线程的数量. 执行任务时将重用存在先前创建的线程(如果池中存在可用线程的话). 如果池中没有可用线程, 将创建一个新的线程, 并将其添加到池中. 池中的线程超过60秒未被使用就会被销毁, 因此长时间保持空闲的CachedThreadPool不会消耗额外的资源.

    public static ExecutorService newSingleThreadExecutor(): 创建一个单线程的Executor. 这个Executor保证按照任务提交的顺序依次执行任务.

    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize): 创建一个可重用的固定线程数的线程池. ScheduledExecutorService是ExecutorService的子接口, 调用ScheduledExecutorService的相关方法, 可以延迟或定期执行任务.

    以上静态方法均使用默认的ThreadFactory(即Executors.defaultThreadFactory()方法的返回值)创建线程, 如果想要指定ThreadFactory, 可调用他们的重载方法.通过指定ThreadFactory, 可以定制新建线程的名称, 线程组, 优先级, 守护线程状态等.

    如果Executors提供的创建线程池的方法无法满足要求, 可以使用ThreadPoolExecutor类创建线程池.

     

    提交任务. 所有的线程池都是ExecutorService及其子类的对象, 因此, 可以调用ExecutorService的相关方法提交任务.

    void execute(Runnable command): 使用池中已存在的线程或新建一个线程执行command. 


    1. public class ExecutorsDemo {  
    2.     public static void main(String[] args) throws Exception {  
    3.         System.out.println("----------------FixedThreadPool---------------------");  
    4.         ExecutorService fixedPool = getFixedThreadPool();  
    5.         executeThread(fixedPool);  
    6.           
    7.         // 为了避免混淆, 需要等待executeThread(fixedPool)执行完成  
    8.         Thread.sleep(3000);  
    9.           
    10.         System.out.println("----------------CashedThreadPool---------------------");  
    11.         ExecutorService cashedPool = getCashedThreadPool();  
    12.         executeThread(cashedPool);  
    13.           
    14.         // 为了避免混淆, 需要等待executeThread(cashedPool)执行完成  
    15.         Thread.sleep(3000);  
    16.           
    17.         System.out.println("----------------SingleThreadExecutor---------------------"); 
    18.         ExecutorService singleExecutor = getSingleThreadExecutor();  
    19.         executeThread(singleExecutor);  
    20.           
    21.     }  
    22.       
    23.     // 只存在一个线程的线程池  
    24.     private static ExecutorService getSingleThreadExecutor() {  
    25.         return Executors.newSingleThreadExecutor();  
    26.     }  
    27.   
    28.     // 创建一个根据需要自动调整大小的线程池  
    29.     private static ExecutorService getCashedThreadPool() {  
    30.         return Executors.newCachedThreadPool();  
    31.     }  
    32.   
    33.     // 创建一个可重用的固定线程数的线程池  
    34.     private static ExecutorService getFixedThreadPool() {  
    35.         return Executors.newFixedThreadPool(2);  
    36.     }  
    37.       
    38.     private static void executeThread(ExecutorService pool) {  
    39.         Thread t1 = new MyThread();  
    40.         Thread t2 = new MyThread();  
    41.         Thread t3 = new MyThread();  
    42.         Thread t4 = new MyThread();  
    43.         // 将Tread放入线程池中执行  
    44.         // MyThread类继承自Thread, 而Thread类实现了Runnable接口  
    45.         pool.execute(t1);  
    46.         pool.execute(t2);  
    47.         pool.execute(t3);  
    48.         pool.execute(t4);  
    49.         // 关闭线程池  
    50.         pool.shutdown();  
    51.     }  
    52.       
    53.     private static final class MyThread extends Thread {  
    54.         @Override  
    55.         public void run() {  
    56.             super.run();  
    57.             System.out.println(Thread.currentThread().getName() + ": is running!");  
    58.         }  
    59.     }  
    60. }  
    61.  

    程序的输出为:

     

    ----------------FixedThreadPool---------------------

    pool-1-thread-1: is running!

    pool-1-thread-2: is running!

    pool-1-thread-2: is running!

    pool-1-thread-1: is running!

    ----------------CashedThreadPool---------------------

    pool-2-thread-1: is running!

    pool-2-thread-2: is running!

    pool-2-thread-4: is running!

    pool-2-thread-3: is running!

    ----------------SingleThreadExecutor---------------------

    pool-3-thread-1: is running!

    pool-3-thread-1: is running!

    pool-3-thread-1: is running!

    pool-3-thread-1: is running!

     
     关闭线程池. 使用完线程池后需要关闭它, 否则程序可能一直处于运行状态. ExecutorService提供了2个方法用于关闭线程池:

    void shutdown(): 关闭线程池, 不再接受新任务. 如果存在正在执行的任务, 则等待任务执行完成.

    List<RunnableshutdownNow(): 关闭线程池, 不再接受新任务. 尽力尝试停止正在执行的任务, 并返回正在等待的任务列表.

    boolean isShutdown(): 判断线程池是否已经关闭.



     
  • 相关阅读:
    CREATE AGGREGATE
    技术文档列表
    jQuery 判断表单中多个 input text 中至少有一个不为空
    Java实现 蓝桥杯 算法提高 奥运会开幕式
    Java实现 蓝桥杯 算法提高 最长滑雪道
    Java实现 蓝桥杯 算法提高 最长滑雪道
    Java实现 蓝桥杯 算法提高 最长滑雪道
    Java实现 蓝桥杯 算法提高 最大值路径
    Java实现 蓝桥杯 算法提高 最大值路径
    Java实现 蓝桥杯 算法提高 最大值路径
  • 原文地址:https://www.cnblogs.com/signheart/p/6606476.html
Copyright © 2011-2022 走看看