iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Java线程池如何创建
  • 754
分享到

Java线程池如何创建

2023-06-29 14:06:54 754人浏览 独家记忆
摘要

本文小编为大家详细介绍“Java线程池如何创建”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java线程池如何创建”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。线程池的好处可以实现线程的复用,避免重新创建线程和

本文小编为大家详细介绍“Java线程池如何创建”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java线程池如何创建”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

线程池的好处

  • 可以实现线程的复用,避免重新创建线程和销毁线程。创建线程和销毁线程对CPU的开销是很大的。

  • 可以限制最大可创建的线程数,可根据自己的机器性能动态调整线程池参数,提高应用性能。

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

  • 统一管理线程。

创建线程池的五种方式

缓存线程池(不推荐)

固定容量线程池(不推荐)

单个线程池(不推荐)

定时任务线程池(不推荐)

通过ThreadPoolExecutor构造方法创建线程池(阿里巴巴开发手册十分推荐)

前面4种创建线程池的方式都是通过Executors的静态方法来创建。

缓存线程池CachedThreadPool

ExecutorService executorService = Executors.newCachedThreadPool();        for (int i = 0; i < 10; i++) {            final int finalI = i;            executorService.execute(new Runnable() {                public void run() {                    System.out.println(Thread.currentThread().getName()+"<thread->run>"+ finalI);                }            });        }

为什么不推荐使用缓存线程池?

源码分析

public static ExecutorService newCachedThreadPool() {        return new ThreadPoolExecutor(0, 2147483647, 60L, TimeUnit.SECONDS, new SynchronousQueue());    }
 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, Executors.defaultThreadFactory(), defaultHandler);    }

通过上面两个代码片段,我们可以看出CachedThreadPool的maximumPoolSize为Integer的最大值2147483647,相当于可以无限的创建线程,而创建线程是需要内存的,这样就会造成内存溢出,而且一般的机器也没用那么大的内存给它创建这么大量的线程。

固定容量线程池FixedThreadPool

newFixedThreadPool(int num),num就是我们要指定的固定线程数量

ExecutorService executorService = Executors.newFixedThreadPool(5);      for (int i = 0; i < 10; i++) {          final int finalI = i;          executorService.execute(new Runnable() {              public void run() {                  System.out.println(Thread.currentThread().getName()+"<thread->run>"+ finalI);              }          });      }

输出:

pool-1-thread-5<thread->run>4
pool-1-thread-4<thread->run>3
pool-1-thread-5<thread->run>5
pool-1-thread-3<thread->run>2
pool-1-thread-3<thread->run>8
pool-1-thread-3<thread->run>9
pool-1-thread-2<thread->run>1
pool-1-thread-1<thread->run>0
pool-1-thread-5<thread->run>7
pool-1-thread-4<thread->run>6

可以看出起到了线程的复用。

为什么FixedThreadPool是固定线程池?

源码分析

public static ExecutorService newFixedThreadPool(int nThreads) {        return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue());    }

通过这个源码可以看出,核心线程数(corePoolSize)和最大线程数(maximumPoolSize)都为nThreads,因为只有这样,线程池才不会进行扩容,线程数才固定。

单个线程池SingleThreadExecutor

ExecutorService executorService = Executors.newSingleThreadExecutor();      for (int i = 0; i < 10; i++) {          final int finalI = i;          executorService.execute(new Runnable() {              public void run() {                  System.out.println(Thread.currentThread().getName()+"<thread->run>"+ finalI);              }          });      }

为什么SingleThreadExecutor只含有一个线程?

源码分析

public static ExecutorService newSingleThreadExecutor() {        return new Executors.FinalizableDelegatedExecutorService(new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue()));    }

通过这个源码可以看出,核心线程数(corePoolSize)和最大线程数(maximumPoolSize)都为1,所以它只含有一个线程。

定时任务线程池ScheduledThreadPool

  int initDelay=10; //初始化延时      int period=1;//初始化延迟过了之后,每秒的延时      ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);      scheduledExecutorService.scheduleAtFixedRate(new Runnable() {          @Override          public void run() {              System.out.println(Thread.currentThread().getName()+"<thread->run>");          }      },initDelay,period, TimeUnit.SECONDS);

这段代码的效果是:程序运行之后等10秒,然后输出第一次结果,之后每隔1秒输出一次结果。

为什么不推荐使用ScheduledThreadPool?

源码分析

public ScheduledThreadPoolExecutor(int corePoolSize) {        super(corePoolSize, 2147483647, 10L, TimeUnit.MILLISECONDS, new ScheduledThreadPoolExecutor.DelayedWorkQueue());    }

可以看出ScheduledThreadPool的最大线程数(maximumPoolSize)为Integer的最大值2147483647,相当于可以无限的创建线程,而创建线程是需要内存的,这样就会造成内存溢出,而且一般的机器也没用那么大的内存给它创建这么大量的线程。

ThreadPoolExecutor创建线程池(十分推荐)

ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 20,              2L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5),              Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());      for (int i = 0; i < 12; i++) {          final int finalI = i;          threadPoolExecutor.execute(new Runnable() {              public void run() {                  System.out.println(Thread.currentThread().getName()+"<thread->run>"+ finalI);              }          });      }
ThreadPoolExecutor的七个参数详解
public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {            }
  • corePoolSize:核心线程数。这些线程一旦被创建不会被销毁,是一直存在的。线程池默认是没有线程的,当有任务到来了,就会通过ThreadFactory去创建线程,并一直存在。

  • maximumPoolSize:最大线程数。非核心线程数=maximumPoolSize-corePoolSize,非核心线程数其实就是可扩容的线程数,可能会被销毁。

  • keepAliveTime:非核心线程的空闲存活时间。当通过扩容生成的非核心线程数在keepAliveTime这个时间后还处于空闲状态,则会销毁这些非核心线程。

  • unit:keepAliveTime的时间单位,例如:秒

  • workQueue:等待区。当来了>corePoolSize的任务时会把任务存放在workQueue这个阻塞队列中,等待其他线程处理。

  • threadFactory:线程工厂。创建线程的一种方式。

  • handler:拒绝策略。当来了>最大线程数+workQueue的容量则会执行拒绝策略

workQueue

ArrayBlockingQueue:有界阻塞队列。队列有大小限制,当容量超过时则会触发扩容或者拒绝策略。

public ArrayBlockingQueue(int capacity) {        this(capacity, false);    }

LinkedBlockingQueue:无界阻塞队列,队列无大小限制,可能会造成内存溢出。

 public LinkedBlockingQueue() {        this(2147483647);    }
handler

AbortPolicy:直接抛异常

public static class AbortPolicy implements RejectedExecutionHandler {        public AbortPolicy() {        }        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {            throw new RejectedExecutionException("Task " + r.toString() + " rejected from " + e.toString());        }    }

DiscardPolicy:不作任何操作。默默丢弃任务

public static class DiscardPolicy implements RejectedExecutionHandler {        public DiscardPolicy() {        }        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {        }    }

DiscardOldestPolicy:丢掉存在时间最长的任务

public static class DiscardOldestPolicy implements RejectedExecutionHandler {        public DiscardOldestPolicy() {        }        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {            if (!e.isshutdown()) {                e.getQueue().poll();                e.execute(r);            }        }    }

CallerRunsPolicy:让提交任务的线程去处理任务

public static class CallerRunsPolicy implements RejectedExecutionHandler {        public CallerRunsPolicy() {        }        public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {            if (!e.isShutdown()) {                r.run();            }        }    }

threadFactory

ThreadFactory threadFactory = Executors.defaultThreadFactory();      threadFactory.newThread(new Runnable() {          @Override          public void run() {              System.out.println("threadFactory");          }      }).start();
如何触发拒绝策略和线程池扩容?
ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10, 20,              2L, TimeUnit.SECONDS, new ArrayBlockingQueue<>(5),              Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());      for (int i = 0; i < 26; i++) { //并发数26          final int finalI = i;          threadPoolExecutor.execute(new Runnable() {              public void run() {                  System.out.println(Thread.currentThread().getName()+"<thread->run>"+ finalI);              }          });      }      
  • 为什么这段代码会触发拒绝策略

对于这段代码,如果来了26个并发,10个并发会被核心线程处理,5个会在等待区,剩下11个会因为等待区满了而触发扩容,但是又因为因为这里最多能够扩容10个,这里却是11个,所以会触发拒绝策略。

  • 怎么触发扩容

触发扩容:并发数>核心线程数(corePoolSize)+阻塞队列(workQueue)的大小

  • 使用Java纯手写一个线程池

读到这里,这篇“Java线程池如何创建”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网精选频道。

--结束END--

本文标题: Java线程池如何创建

本文链接: https://www.lsjlt.com/news/325278.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java线程池如何创建
    本文小编为大家详细介绍“Java线程池如何创建”,内容详细,步骤清晰,细节处理妥当,希望这篇“Java线程池如何创建”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。线程池的好处可以实现线程的复用,避免重新创建线程和...
    99+
    2023-06-29
  • Java如何手动创建线程池
    目录如何手动创建线程池构造器队列饱和策略示例源码分析线程池工具类实现线程的三种方式使用ThreadPoolExecutor编写线程池工具类如何手动创建线程池 jdk提供了一个通过Th...
    99+
    2022-11-13
  • Android如何创建线程池
    在Android中,可以使用`ThreadPoolExecutor`类来创建线程池。下面是创建线程池的步骤:1. 导入所需的类:``...
    99+
    2023-09-12
    Android
  • springboot如何创建线程池
    这篇文章主要介绍springboot如何创建线程池,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!springboot创建线程池两种方式1.使用static代码块创建这样的方式创建的好处是当代码用到线程池的时候才会初始...
    99+
    2023-06-22
  • Java线程池ThreadPoolExecutor怎么创建
    本篇内容介绍了“Java线程池ThreadPoolExecutor怎么创建”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!简介ThreadPo...
    99+
    2023-07-02
  • Java多线程 - 创建线程池的方法 - ThreadPoolExecutor和Executors
    文章目录 线程池(重点)线程池介绍实现线程池的方式方式一: 实现类ThreadPoolExecutorThreadPoolExecutor构造器的参数线程池处理Runnable任务线程池处理Callable任务 方式二: ...
    99+
    2023-08-30
    java jvm 开发语言
  • java线程池创建的方法是什么
    在Java中,线程池可以使用以下两种方法来创建: 使用`Executors`类中的静态方法来创建线程池: ExecutorSer...
    99+
    2023-10-25
    java
  • java如何创建线程
    Java使用Thread类代表线程,所有的线程对象都必须是Thread类或其子类的实例。Java可以用三种方式来创建线程,如下所示:1)继承Thread类创建线程2)实现Runnable接口创建线程3)使用Callable和Future创建...
    99+
    2016-03-22
    java基础 java 线程
  • java创建线程池一共有七种方式
    java创建线程池一共有七种方式 这 7 种实现方法分别是: Executors.newFixedThreadPool:创建一个固定大小的线程池,可控制并发的线程数,超出的线程会在队列中等待。 Exe...
    99+
    2023-09-13
    java 开发语言
  • java中线程池创建的方式有哪些
    本篇文章为大家展示了java中线程池创建的方式有哪些,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Java可以用来干什么Java主要应用于:1. web开发;2. Android开发;3. 客户端开...
    99+
    2023-06-14
  • SpringBoot 项目中创建线程池
     前言: 前两天做项目的时候,想提高一下插入表的性能优化,因为是两张表,先插旧的表,紧接着插新的表,一万多条数据就有点慢了 后面就想到了线程池ThreadPoolExecu...
    99+
    2022-11-13
  • Java创建线程池为什么一定要用ThreadPoolExecutor
    目录先说结论OOM风险演示内存溢出原因分析使用ThreadPoolExecutor来改进其他创建线程池的问题总结前言: 在 Java 语言中,并发编程都是依靠线程池完成的,而线程池的...
    99+
    2022-11-13
  • 如何在java中创建线程
    本篇文章为大家展示了如何在java中创建线程,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Java可以用来干什么Java主要应用于:1. web开发;2. Android开发;3. 客户端开发;4....
    99+
    2023-06-14
  • 详解Java线程池的使用(7种创建方法)
    目录 1. 固定数量的线程池a.  线程池返回结果b. ⾃定义线程池名称或优先级2. 带缓存的线程池3. 执⾏定时任务 a.&nbs...
    99+
    2023-03-24
    Java线程池 Java线程池使用 线程池
  • java线程池的四种创建方式详细分析
    目录前言1. 线程池2. 创建方式前言 在讲述线程池的前提 先补充一下连接池的定义 连接池是创建和管理一个连接的缓冲池的技术,这些连接准备好被任何需要它们的线程使用 可以看到其连接池...
    99+
    2022-11-13
  • 怎么在java中使用ThreadPoolExecutor创建一个线程池
    这篇文章给大家介绍怎么在java中使用ThreadPoolExecutor创建一个线程池,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。Java可以用来干什么Java主要应用于:1. web开发;2. Android开发...
    99+
    2023-06-14
  • Java中的异步与线程池怎么创建使用
    这篇文章主要介绍“Java中的异步与线程池怎么创建使用”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java中的异步与线程池怎么创建使用”文章能帮助大家解决问题。初始化线程的4种方式1.继承Thre...
    99+
    2023-07-04
  • 线程池的创建方式有哪些
    这篇文章主要讲解了“线程池的创建方式有哪些”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“线程池的创建方式有哪些”吧!什么是线程池线程池(ThreadPool...
    99+
    2022-10-19
  • Springboot 配置线程池创建线程及配置 @Async 异步操作线程池详解
    目录前言一、创建一个Springboot Web项目二、新建ThreadPoolConfig三、新建controller测试四、演示结果前言 众所周知,创建显示线程和直接使用未配置的...
    99+
    2022-11-13
  • java中线程池最实用的创建与关闭指南
    目录前言线程池创建 只需要执行shutdown就可以优雅关闭 执行shutdownNow关闭的测试 总结前言 在日常的开发工作当中,线程池往往承载着一个应用中最重要的业务逻辑,因此我...
    99+
    2022-11-12
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作