• Java提供的几种线程池


    线程池,顾名思义,放线程的池子嘛,这个池子可以存放多少线程取决于你自己采用什么样的线程池,你的硬件资源,以及并发线程的数量。JDK提供了下面的四种线程池:

    固定线程数的线程池 

    1、最简单的

    在Java中创建一个线程池,这很简单,只需要两行代码。

     1 ExecutorService executor = Executor.newFixedTreadPool(6);//固定线程是6
     2 //线程一般设置成processor核心数的倍数,因为我这台机器是6核的,所以设成6。这也是充分利用硬件嘛
     3 
     4 //执行线程任务
     5 executor.execute(new Runnable(){
     6 @Override
     7 public void run(){
     8      //do nothing 
     9 }
    10 })
    11     
    12 executor.shutdown();

    Executor是Java并发包中提供的,用来创造不同类型的线程池。

    Attention

    但是在多人合作或者是一些部署上线的项目里,是不允许去使用这种方法的,因为它是有性能隐患的。

    Executors在创建线程池的时候,用的是new LinkedBlockingQueue(),它这个队列本身是无边界的,但是线程是固定数量的。这就意味着,在程序运行的过程中,最多会有N个线程在处于活动状态。每次有新的任务来就会等待,直到有线程处于空闲状态。所有的线程都会处于线程池里里面,直到shutdown()的执行。

    它的问题就在于来者不拒,只要有任务来,你就进队列等着。在入队列和出队列用的并不是同一个lock,在多processor的机器上,是可以做到真正意义上的并行的。拿经典的生产者和消费者来举例子,在同一个时间点,有的在消费,有的在生产。

    这种线程池不会销毁线程,不会拒绝任务,固定线程数。所以如果不停的加入任务,会导致很糟糕的内存占用,老年代可能会被占满。

    2、稍复杂的(可以延时执行,也可以执行带返回值的任务)

     1 public static void main(String[] args) throws InterruptedException, ExecutionException {
     2         TestThread testThread = new TestThread();
     3         System.out.println(testThread.processors);
     4 
     5         ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(6);
     6         FutureTask<String> futureTask = new FutureTask<>(new Callable<String>() {
     7             @Override
     8             public String call() throws Exception {
     9                 return Thread.currentThread().getName();
    10             }
    11         });
    12         scheduledExecutorService.submit(futureTask);
    13 
    14         //获取返回值
    15         String result = futureTask.get();
    16         System.out.println("result :"+result);
    17 
    18         //执行延时任务
    19         scheduledExecutorService.schedule(new Runnable() {
    20             @Override
    21             public void run() {
    22                 System.out.println(Thread.currentThread().getName()+": bomb!");
    23             }
    24         },3L,TimeUnit.SECONDS);
    25     }

    3、缓存的线程池

    核心池大小为0,线程池最大线程数目为最大整型,这意味着所有的任务一提交就会wait。当线程池中的线程有60s没有执行任务就会被Kill,阻塞队列为SynchronousQueue。SynchronousQueue的take操作需要put操作等待,put操作需要take操作等待,否则会阻塞(线程池的阻塞队列不能存储,所以当目前线程处理忙碌状态时,会开辟新的线程来处理请求**),线程进入wait set。

    总结一下这是一个可以无限扩大的线程池;适合处理执行时间比较小的任务;线程空闲时间超过60s就会被Kill,所以长时间处于空闲状态的时候,这种线程池几乎不占用资源,因为它压根没有线程在里面;阻塞队列没有存储空间,只要请求到来,就必须找到一条空闲线程去处理这个请求,找不到则在线程池新开辟一条线程。

    如果主线程提交任务的速度远远大于CachedThreadPool的处理速度,则CachedThreadPool会不断地创建新线程来执行任务,这样有可能会导致系统耗尽CPU和内存资源,所以在使用该线程池时,要注意控制并发的任务数。如果是一个不断增长的任务需求,很容易就会到性能瓶颈,它会不停的创建新的线程。

     1 ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
     2         for (int i = 0; i < 10; i++) {
     3             cachedThreadPool.execute(new Runnable() {
     4                 @Override
     5                 public void run() {
     6                     System.out.println(Thread.currentThread().getName());
     7                 }
     8             });
     9         }
    10         cachedThreadPool.shutdown();

    4、单个线程的线程池

    SingleThreadExecutor 是使用单个worker线程的Executor。只有一种情况会有新的线程加入线程池,那就是原有的线程运行时有抛出异常,这时就会有创建的新的线程来替代它的工作。

    拿生产者消费者模型来说的话,这就是一个单一消费者的模型

    (ps.一般可以用来做一些日志记录)

     1 public static void main(String[] args) {
     2         // 永远是一条线程
     3         ExecutorService singleThreadPool = Executors.newSingleThreadExecutor();
     4         for (int i = 0; i < 10; i++) {
     5             final int j = i;
     6             singleThreadPool.execute(new Runnable() {
     7                 @Override
     8                 public void run() {
     9                     System.out.println(Thread.currentThread().getName() + ":" + j);
    10                 }
    11             });
    12         }
    13         singleThreadPool.shutdown();
    14         
    15     }

  • 相关阅读:
    Java8 Stream Function
    PLINQ (C#/.Net 4.5.1) vs Stream (JDK/Java 8) Performance
    罗素 尊重 《事实》
    小品 《研发的一天》
    Java8 λ表达式 stream group by max then Option then PlainObject
    这人好像一条狗啊。什么是共识?
    TOGAF TheOpenGroup引领开发厂商中立的开放技术标准和认证
    OpenMP vs. MPI
    BPMN2 online draw tools 在线作图工具
    DecisionCamp 2019, Decision Manager, AI, and the Future
  • 原文地址:https://www.cnblogs.com/zsh-blogs/p/11255527.html
Copyright © 2020-2023  润新知