zoukankan      html  css  js  c++  java
  • 44 创建线程池有哪几种方式?

    创建线程池有哪几种方式?

    答:

    Java四种线程池 :

    Java里面线程池的顶级接口是Executor,但是严格意义上讲Executor并不是一个线程池,而只是一个执行线程的工具。真正的线程池接口是ExecutorService。

    下面这张图完整描述了线程池的类体系结构:


     

    1. newCachedThreadPool

    创建一个可根据需要创建新线程的线程池,但是在以前构造的线程可用时将重用它们。对于执行很多短期异步任务的程序而言,这些线程池通常可提高程序性能。调用 execute 将重用以前构造的线程(如果线程可用)。如果现有线程没有可用的,则创建一个新线程并添加到池中。终止并从缓存中移除那些已有 60 秒钟未被使用的线程。因此,长时间保持空闲的线程池不会使用任何资源。

    public static ExecutorService newCachedThreadPool()

    public class ThreadPoolExecutorTest {
       public static void main(String[] args ) {
    
    //可缓存的线程池,如果线程池的容量超过了任务数,自动回收空闲线程
        ExecutorService cacheThreadPool =Executors.newCachedThreadPool();
    
    //测试可缓存线程池
         for(int i =1;i<=5;i++){
           final int index=i ;
           try{
            Thread.sleep(1000);
          }catch(InterruptedException e ) {
             e.printStackTrace();
          }
           cacheThreadPool.execute(new Runnable(){
             @Override
             public void run() {
              System.out.println("第" +index +"个线程" +Thread.currentThread().getName());  
            }  
          });
        }
      }
    }
    
    
    //输出结果
    第1个线程pool-1-thread-1
    第2个线程pool-1-thread-1
    第3个线程pool-1-thread-1
    第4个线程pool-1-thread-1 第5个线程pool-1-thread-1  
    

    由结果可看出 当执行第二个任务时第一个任务已经完成,会复用执行第一个任务的线程,而不用每次新建线程。
     

    1. newFixedThreadPool

    创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程,如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。

    public static ExecutorService newFixedThreadPool(int nThreads)

    ( nThreads - 池中的线程数 )

    public class ThreadPoolExecutorTest {
       public static void main(String[] args) {
    
    //定长线程池,每当提交一个任务就创建一个线程,直到达到线程池的最大数量,这时线程数量不再变化
        ExecutorService fixedThreadPool =Executors. newFixedThreadPool(3);
    
    //测试定长线程池,线程池的容量为3,提交5个任务,根据打印结果可以看出先执行前3个任务,3个任务结束后再执行后面的任务
         for (int i =1; i<=5;i++){
           final int index=i ;
           fixedThreadPool.execute(new Runnable(){
             @Override
             public void run() {
               try {
                System.out.println("第" +index + "个线程" +Thread.currentThread().getName());
                Thread.sleep(1000);
              } catch(InterruptedException e ) {
                 e .printStackTrace();
              }
            }
    
          });
        }
      }
    }
    

    由于设置最大线程数为3,所以在输出三个数后等待2秒后才继续输出。
     

    1. newScheduledThreadPool

    创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。

    public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

    ( corePoolSize - 池中所保存的线程数,即使线程是空闲的也包括在内。 )

    第一个延迟执行示例代码:

    public class ThreadPoolExecutorTest {  
      public static void main(String[] args) {
        ScheduledExecutorService scheduledThreadPool= Executors.newScheduledThreadPool(3);   
        scheduledThreadPool.schedule(newRunnable(){     
          @Override 
          public void run() {
           System.out.println("延迟三秒");
           }
       }, 3, TimeUnit.SECONDS);
      }
    }
    

    表示延迟3秒执行。
     

    第二个定期执行示例代码:

    public class ThreadPoolExecutorTest {  
      public static void main(String[] args) {
    
    //定长线程池,可执行周期性的任务
        ScheduledExecutorService scheduledThreadPool= Executors.newScheduledThreadPool(3);    
      scheduledThreadPool.scheduleAtFixedRate(newRunnable(){    
        @Override      
        public void run() {
           System.out.println("延迟1秒后每三秒执行一次");
         }
       },1,3,TimeUnit.SECONDS);
     }
    
    }
    

    表示延迟1秒后每3秒执行一次。
     

    1. newSingleThreadExecutor

    创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程。(注意,如果因为在关闭前的执行期间出现失败而终止了此单个线程,那么如果需要,一个新线程将代替它执行后续的任务)。可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。与其他等效的 newFixedThreadPool(1)不同,可保证无需重新配置此方法所返回的执行程序即可使用其他的线程。

    public static ExecutorService newSingleThreadExecutor()

    public class ThreadPoolExecutorTest {  
      public static void main(String[] args) {
    
    //单线程的线程池,线程异常结束,会创建一个新的线程,能确保任务按提交顺序执行
        ExecutorService singleThreadPool= Executors.newSingleThreadExecutor();    
    
    //测试单线程的线程池
        for(int i=1;i<=5;i++){      
          int index=i;      
        singleThreadPool.execute(new Runnable(){
           @Override
           public void run() {         
            try{
             System.out.println("第"+index+"个线程");
            Thread.sleep(2000);
             }catch(InterruptedException e) {            
              e.printStackTrace();
            }
          } });
        }
      }
    }
    

     

    原文链接: https://www.jb51.net/article/107940.htm
     

    拓展:

    一、线程池使用场景

    • 单个任务处理时间短

    • 将需处理的任务数量大

    二、使用Java线程池好处

    1. 使用new Thread()创建线程的弊端:
    • 每次通过new Thread()创建对象性能不佳。

    • 线程缺乏统一管理,可能无限制新建线程,相互之间竞争,及可能占用过多系统资源导致死机或oom。

    • 缺乏更多功能,如定时执行、定期执行、线程中断。

    1. 使用Java线程池的好处:
    • 重用存在的线程,减少对象创建、消亡的开销,提升性能。

    • 可有效控制最大并发线程数,提高系统资源的使用率,同时避免过多资源竞争,避免堵塞。

    • 提供定时执行、定期执行、单线程、并发数控制等功能。

  • 相关阅读:
    Kubernetes --- 详细介绍和架构详解
    使用kubeadm方式安装K8S
    ResourceManager学习之Application,状态机管理
    ResourceManager学习之ApplicationMaster,NodeManager管理
    ResourceManager基本职能和内部架构
    YARN底层基础库
    Hadoop RPC机制详解
    Yarn介绍(设计理念与基本架构)
    Flume 初探
    Python
  • 原文地址:https://www.cnblogs.com/ynzj123/p/12825267.html
Copyright © 2011-2022 走看看