多线程(七)JDK原生线程池

我会带着你远行 2024-02-18 21:56 152阅读 0赞

如同数据库连接一样,线程的创建、切换和销毁同样会耗费大量的系统资源。为了复用创建好的线程,减少频繁创建线程的次数,提高线程利用率可以引用线程池技术。使用线程池的优势有如下几点:
1、保持一定数量的线程,减少了线程频繁创建和销毁资源消耗。
2、使用线程的时候直接由线程池中取出线程,省去了创建线程的时间,侧面提高了系统的响应时间。
3、需要使用线程的时候直接从线程池中取出,避免了人为的不合理创建线程,减少了潜在的风险。
Doug Lea在实现JUC中提供了原生的线程池,并提供了各种线程管理策略来适应于不同的使用场景。使用的时候可通过Executors获取各种线程池实例。

837242-20170902085018062-563596047.png

这里提供了六对12个方法来创建ExecutorService,其中每种类型的ExecutorService可以适用于不同的应用场景,对线程的管理策略也各不相同。下面就看一下各个方法的注释:

复制代码

  1. /**
  2. * Creates a thread pool that creates new threads as needed, but will reuse previously constructed threads when they are available.
  3. * 创建一个线程池,需要的时候会创建新的线程,如果有可用的线程则会复用以前已经创建好的线程。
  4. * These pools will typically improve the performance of programs that execute many short-lived asynchronous tasks.
  5. * 这些线程池通常情况下可以提升哪些短期异步任务的性能
  6. * Calls to {@code execute} will reuse previously constructed threads if available.
  7. * 如果以创建的线程状态可用的话,调用execute可以复用他们
  8. * If no existing thread is available, a new thread will be created and added to the pool.
  9. * 如果不存在可用状态的线程,那么将会创建一个新线程同时会把该线程添加到线程池中
  10. * Threads that have not been used for sixty seconds are terminated and removed from the cache.
  11. *那些超过60s没用的线程将会被销毁同时从缓存中移除
  12. * Thus, a pool that remains idle for long enough will not consume any resources.
  13. *因此长时间空闲的线程池不会消耗任何资源
  14. * Note that pools with similar properties but different details (for example, timeout parameters) may be created using {@link ThreadPoolExecutor} constructors.
  15. *可以使用ThreadPoolExecutor创建性质相似但实现细节不同的线程池
  16. * @return the newly created thread pool
  17. */
  18. public static ExecutorService newCachedThreadPool();
  19. //可以使用自定义的ThreadFactory 类创建线程,其它和无参方法一致
  20. public static ExecutorService newCachedThreadPool(ThreadFactory threadFactory);

复制代码

复制代码

  1. /**
  2. * Creates a thread pool that reuses a fixed number of threads operating off a shared unbounded queue.
  3. *创建一个可重用、固定数量线程的线程池
  4. * At any point, at most {@code nThreads} threads will be active processing tasks.
  5. *任何时间最多只有 nThreads 个线程被激活来执行任务
  6. * If additional tasks are submitted when all threads are active, they will wait in the queue until a thread is available.
  7. * 当无可用空闲线程的时候,如果有新任务被提交,这些新任务将会一直等待直至有可用线程来执行。
  8. * If any thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks.
  9. *如果任何线程正常关闭之前在执行过程中因失败而提前终止,那么如果有未被执行的后续任务,则会创建新的线程来继续执行。
  10. * The threads in the pool will exist until it is explicitly {@link ExecutorService#shutdown shutdown}.
  11. * 线程池中的所有线程在明确掉用shutdown之后将会退出
  12. *
  13. * @param nThreads the number of threads in the pool
  14. * @return the newly created thread pool
  15. * @throws IllegalArgumentException if {@code nThreads <= 0}
  16. */
  17. public static ExecutorService newFixedThreadPool(int nThreads);
  18. //可自定义ThreadFactory
  19. public static ExecutorService newFixedThreadPool(int nThreads, ThreadFactory threadFactory);

复制代码

复制代码

  1. /**
  2. * Creates a thread pool that can schedule commands to run after a given delay, or to execute periodically.
  3. * 创建一个线程池,该线程在延迟指定时间之后可以周期性的执行线程体
  4. * @param corePoolSize the number of threads to keep in the pool,
  5. * even if they are idle
  6. * @return a newly created scheduled thread pool 注意返回值类型是ScheduledExecutorService,不要使用ExecutorService来接收,否则找不到schedule执行方法
  7. * @throws IllegalArgumentException if {@code corePoolSize < 0}
  8. */
  9. public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize);
  10. //可自定义ThreadFactory
  11. public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize, ThreadFactory threadFactory);

复制代码

复制代码

  1. /**
  2. * Creates an Executor that uses a single worker thread operating off an unbounded queue.
  3. *创建一个Executor,使用一个线程来工作,该线程存储在LinkedBlockingQueue中
  4. * (Note however that if this single thread terminates due to a failure during execution prior to shutdown, a new one will take its place if needed to execute subsequent tasks.)
  5. *注,如果任何线程正常关闭之前在执行过程中因失败而提前终止,那么如果有未被执行的后续任务,则会创建新的线程来继续执行。
  6. * Tasks are guaranteed to execute sequentially, and no more than one task will be active at any given time.
  7. * 任务是按顺序执行的,任何时间都只有一个线程来执行任务
  8. * Unlike the otherwise equivalent {@code newFixedThreadPool(1)} the returned executor is guaranteed not to be reconfigurable to use additional threads.
  9. *
  10. * @return the newly created single-threaded Executor
  11. */
  12. public static ExecutorService newSingleThreadExecutor();
  13. //可自定义ThreadFactory
  14. public static ExecutorService newSingleThreadExecutor(ThreadFactory threadFactory);

复制代码

复制代码

  1. /**
  2. * Creates a single-threaded executor that can schedule commands
  3. * to run after a given delay, or to execute periodically.
  4. * (Note however that if this single
  5. * thread terminates due to a failure during execution prior to
  6. * shutdown, a new one will take its place if needed to execute
  7. * subsequent tasks.) Tasks are guaranteed to execute
  8. * sequentially, and no more than one task will be active at any
  9. * given time. Unlike the otherwise equivalent
  10. * {@code newScheduledThreadPool(1)} the returned executor is
  11. * guaranteed not to be reconfigurable to use additional threads.
  12. * @return the newly created scheduled executor
  13. */
  14. public static ScheduledExecutorService newSingleThreadScheduledExecutor();
  15. public static ScheduledExecutorService newSingleThreadScheduledExecutor(ThreadFactory threadFactory)

复制代码

使用示例:

复制代码

  1. package thread.blogs.threadpool;
  2. import java.util.concurrent.ExecutorService;
  3. import java.util.concurrent.Executors;
  4. import java.util.concurrent.ThreadFactory;
  5. import java.util.concurrent.TimeUnit;
  6. import java.util.concurrent.atomic.AtomicInteger;
  7. /**
  8. * Created by PerkinsZhu on 2017/8/31 13:59.
  9. */
  10. public class PoolTest {
  11. public static void main(String[] args) {
  12. // testCachedThreadPool();
  13. // testSingleThreadExecutor();
  14. // testFixedThreadPool();
  15. testScheduledThreadPool();
  16. }
  17. private static ThreadFactory myFactory = new MyThreadFactory();
  18. private static void testSingleThreadExecutor() {
  19. //一个一个的依次执行
  20. doHandle(Executors.newSingleThreadExecutor(myFactory));
  21. }
  22. private static void testFixedThreadPool() {
  23. //两个两个的一起执行
  24. doHandle(Executors.newFixedThreadPool(2,myFactory));
  25. }
  26. private static void testCachedThreadPool() {
  27. //10个一起一次性执行完
  28. doHandle(Executors.newCachedThreadPool(myFactory));
  29. }
  30. private static void testScheduledThreadPool() {
  31. //定时周期执行
  32. Executors.newScheduledThreadPool(1,myFactory).scheduleAtFixedRate(runnable, 500, 2000, TimeUnit.MILLISECONDS);
  33. }
  34. private static Runnable runnable = () -> {
  35. sleep(1000);
  36. System.out.println(Thread.currentThread().getName() + " work!!!");
  37. };
  38. private static void doHandle(ExecutorService executorService) {
  39. for (int i = 0; i < 10; i++) {
  40. executorService.execute(runnable);
  41. }
  42. executorService.shutdown();
  43. }
  44. private static void sleep(int time) {
  45. try {
  46. Thread.sleep(time);
  47. } catch (InterruptedException e) {
  48. e.printStackTrace();
  49. }
  50. }
  51. }
  52. class MyThreadFactory implements ThreadFactory {//自定义ThreadFactory
  53. private static final AtomicInteger poolNumber = new AtomicInteger(1);
  54. private final ThreadGroup group;
  55. private final AtomicInteger threadNumber = new AtomicInteger(1);
  56. private final String namePrefix;
  57. MyThreadFactory() {
  58. SecurityManager s = System.getSecurityManager();
  59. group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
  60. namePrefix = "☆☆☆--" + poolNumber.getAndIncrement() + "-****-";
  61. }
  62. public Thread newThread(Runnable r) {
  63. Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
  64. if (t.isDaemon()) {
  65. t.setDaemon(false);
  66. }
  67. if (t.getPriority() != Thread.NORM_PRIORITY) {
  68. t.setPriority(Thread.NORM_PRIORITY);
  69. }
  70. return t;
  71. }
  72. }

复制代码

在使用的时候必须明白各种线程池是否适用于自己的情景,选取合适的线程池进行使用。

=========================================

原文链接:多线程(七)JDK原生线程池转载请注明出处!

=========================================

发表评论

表情:
评论列表 (有 0 条评论,152人围观)

还没有评论,来说两句吧...

相关阅读

    相关 线()JDK原生线

    如同数据库连接一样,线程的创建、切换和销毁同样会耗费大量的系统资源。为了复用创建好的线程,减少频繁创建线程的次数,提高线程利用率可以引用线程池技术。使用线程池的优势有如下几点: