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(): 判断线程池是否已经关闭.



     
  • 相关阅读:
    Pwn2Own 内核 TencentOS
    锤子思维的局限性
    内心宁静 Life
    ANTLRWorks: The ANTLR GUI Development Environment
    汇编 while vs for
    CatBoost is a high-performance open source library for gradient boosting on decision trees
    What is ERP
    专利 案件管理系统
    质量:零缺陷 & 零Bug
    SaaS协会 腾讯千帆
  • 原文地址:https://www.cnblogs.com/signheart/p/6606476.html
Copyright © 2011-2022 走看看