线程池7大参数详解及底层工作原理

  线程池做的主要工作就是控制运行的线程数量,处理过程中将任务放入队列,然后在线程创建后启动这些任务,如果运行线程数量超出了最大线程数量,超出部分需要排队等候,等待其他线程执行完毕,然后线程再从队列中取出任务执行。

线程池的主要特点

  • 线程复用;
  • 控制最大并发数;
  • 管理线程;

优势

  • 降低资源的消耗。通过重复利用已经创建的线程降低线程创建和销毁造成的消耗      
  • 提高响应速度。当任务到达时,任务可以不需要等线程创建就能立即执行。
  • 提高线程可管理性。线程是稀缺资源,如果无限制的创建,不仅会消耗系统资源,还会降低系统的稳定性,使用线程池可以进行统一的分配,调优和监控

线程池的三个使用方式。

  * 线程池三种使用方式
 * 1、Executors.newFixedThreadPool(5) 适合长期任务,性能好
 * 2、Executors.newSingleThreadExecutor() 一个任务一个任务执行,保证顺序性
 * 3、Executors.newCachedThreadPool() 适合短期异步任务或者负载很轻的服务

(1)线程池第一个使用方式:Executors.newFixedThreadPool()

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**

 * 线程池三种使用方式
 * 1、Executors.newFixedThreadPool(5) 适合长期任务,性能好
 * 2、Executors.newSingleThreadExecutor() 一个任务一个任务执行,保证顺序性
 * 3、Executors.newCachedThreadPool() 适合短期异步任务或者负载很轻的服务
 */

public class ThreadPoolDemoOne {
    public static void main(String[] args) {
        // 一个线程池创建5个固定线程
        ExecutorService threadPool = Executors.newFixedThreadPool(5);
        // 线程池第一种使用方式:1、Executors.newFixedThreadPool(5)
        try {
            for (int i = 0; i < 10; i++) {
                threadPool.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + "\t 办理业务");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

程序执行结果如下:最多只有5个线程同时执行任务

(2)线程池第二个使用方式:Executors.newSingleThreadExecutor()

package com.wwl.juc;



import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;



/**

 * 线程池三种使用方式

 * 1、Executors.newFixedThreadPool(5) 适合长期任务,性能好

 * 2、Executors.newSingleThreadExecutor() 一个任务一个任务执行,保证顺序性

 * 3、Executors.newCachedThreadPool() 适合短期异步任务或者负载很轻的服务



 */

public class ThreadPoolDemoTwo {

    public static void main(String[] args) {

        // 一个线程池创建1个线程

        ExecutorService threadPoolTwo = Executors.newSingleThreadExecutor();



        // 线程池第二种使用方式:2、Executors.newSingleThreadExecutor()

        try {

            for (int i = 0; i < 10; i++) {

                threadPoolTwo.execute(() -> {

                    System.out.println(Thread.currentThread().getName() + "\t 办理业务");

                });

            }

        } catch (Exception e) {

            e.printStackTrace();

        }



    }

}

程序执行结果如下:只有单个线程执行任务

(3)线程池第三个使用方式:Executors.newCachedThreadPool()

package com.wwl.juc;



import java.util.concurrent.ExecutorService;

import java.util.concurrent.Executors;



/**

 * 线程池三种使用方式

 * 1、Executors.newFixedThreadPool(5) 适合长期任务,性能好

 * 2、Executors.newSingleThreadExecutor() 一个任务一个任务执行,保证顺序性

 * 3、Executors.newCachedThreadPool() 适合短期异步任务或者负载很轻的服务

 */

public class ThreadPoolDemoThree {

    public static void main(String[] args) throws InterruptedException {

        // 一个线程池创建N个线程

        ExecutorService threadPoolThree = Executors.newCachedThreadPool();



        // 线程池第三种使用方式:3、Executors.newCachedThreadPool()

        for (int i = 0; i < 10; i++) {

            threadPoolThree.execute(() -> {

                System.out.println(Thread.currentThread().getName() + "\t 办理业务");

            });

                     // 模拟长期任务,让线程执行时间变长

//            Thread.sleep(200);

        }



    }

}

程序执行结果如下:Executors.newCachedThreadPool();适合执行短期任务,一个线程池可以创建N个线程,但是模拟长期任务,就只有一个线程执行。

 线程池7大参数源码

通过下图线程池源码可知,线程池有7个参数,但一般只问前5个:

å¨è¿éæå¥å¾çæè¿°

 

线程池7大参数详解


  1. corePoolSize:线程池中的常驻核心线程数
    1. 在创建了线程池后,当有请求任务来之后,就会排池中的线程去执行请求任务,近似理解为今日当值线程。
    2. 当线程池中的线程数目达到corePoolSize后,就会把到达的任务放到缓存队列当中。
  2. maximumPoolSize:线程池能够容纳同时执行的最大线程数,此值必须大于等于1
  3. keepAliveTime:多余的空闲线程的存活时间
    1. 当空闲时间达到keepAIiveTime值时,多余空闲线程会被销毁直到只剩下corePoolSize个线程为止
  4. unit:keepAIiveTime的单位
  5. workQueue:任务队列,被提交但尚未被执行的任务。
  6. threadFactory: 表示生成线程池中工作线程的线程工厂,用于创建线程一般用默认的即可。
  7. handIer:拒绝策略,表示当队列满了并且工作线程大于等于线程池的最大线程数(maximumPoolSize)

线程池底层工作原理


å¨è¿éæå¥å¾çæè¿°

 

当调用线程池的 execute() 方法时,线程池会做出以下判断:

如果当前运行的线程小于线程池的核心线程数,那么马上创建线程完成这个任务。
如果运行中的线程数大于等于线程池的核心线程数,那么将线程放进任务队列等待。
如果此时任务队列已满,且正在运行的线程数小于最大线程数,立即创建非核心线程执行这个任务。
如果此时任务队列已满,且正在运行的线程数等于最大线程数,则线程池会启动饱和拒绝策略来执行。

当一个任务完成时,它会从任务队列的对头去出下一个任务来执行。

当一个线程空闲超过一定时间时,线程池会判断当前运行线程数是否大于核心线程数,如果大于核心线程数,该线程就会被停掉,直至当前线程数等于核心线程数。

你可能感兴趣的:(java基础,java面试题集锦)