线程池详解

1. 线程池的作用

线程是一种有限的宝贵的系统资源,创建线程需要很多时间和系统资源,需要对线程进行回收利用,降低对系统资源的消耗,提升服务器的执行效率。

2. 几种常见的线程池

顶层接口:

Executor

  • execute(Runnable):将任务交给线程池执行

子接口:

ExecutorService

  • shutdown():停止线程池,会等待线程执行完
  • shutdownNow():停止线程池,会终止线程执行

ExecutorService的子接口:

ScheduledExecutorService

  • scheduleWithFixedDelay(执行的Runnable任务,初始的延迟,延迟,时间单位):在固定的延迟时间后执行
  • scheduleAtFixedRate(执行的Runnable任务,初始的延迟,周期,时间单位):在固定的周期后执行

工具类:

Executors提供了一些静态方法,可以帮助我们方便的创建线程池

线程池类型说明
ExecutorService newCachedThreadPool()创建线程个数不限的线程池
ExecutorService newFixedThreadPool(int)创建个数固定的线程池
ExecutorService newSingleThreadExecutor()创建单个线程的线程池
ScheduledExecutorService newScheduledThreadPool(int)创建可以调度的线程池
ExecutorService newWorkStealingPool()创建工作窃取机制的线程池

3. 线程池7大参数意义

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler)
参数说明
corePoolSize核心线程数(线程池初始的线程数,核心线程会一直保留)
maximumPoolSize最大线程数(线程池最大线程数,非核心线程可能被干掉)
keepAliveTime保持存活的时间(非核心线程如果在此时间内没有接收任务,就可能被干掉)
unit存活时间的单位
BlockingQueue用于保存任务的阻塞队列
ThreadFactory线程工厂,用于创建线程
RejectedExecutionHandler拒绝策略(任务数超过最大线程数,拒绝执行任务的方式)

参数的配置

  • 核心线程数

    和cpu核心数以及任务数量和执行时间相关

    核心线程数 = cpu核心数 * n (n >= 1) 上限和任务数以及执行时间相关

    可以使用Runtime.getRuntime().availableProcessors()获得本机的CPU核心数

  • 最大线程数

    最大线程数和核心线程数相同,减少系统创建线程和销毁线程的时间和资源,提高性能

  • keepAliveTime

    如果最大线程数和核心线程数相同,可以设置为0;

    否则可以设置大一点,减少系统创建线程和销毁线程的时间和资源

  • BlockingQueue

    设置为LinkedBlockQueue,任务经常添加和删除时,性能更高

    设置为SynchronousQueue,能处理的任务数更多,吞吐量(每秒处理请求数)更高

  • ThreadFactory、RejectedExecutionHandler

    使用默认配置即可

4. 线程池的原理

线程池的执行过程
在这里插入图片描述
(1)执行任务时判断线程数是否小于核心线程数

(2)如果小于核心线程数就添加核心线程

(3)如果超过核心线程数,就判断是否小于最大线程数

(4)如果小于最大线程数就添加非核心线程

(5)如果超过最大线程数,就执行拒绝策略

线程池的线程如何回收
在这里插入图片描述
(1)通过线程池的execute方法执行任务

(2)通过调用线程池的addWorker方法添加工作线程,同时把Runnable执行任务添加到workQueue中

(3)创建Worker添加到HashSet中,Worker中包含线程

(4)启动Worker中的线程,线程调用runWorker方法

(5)runWorker中判断当前任务是否为空,不为空就执行任务;如果为空,就调用getTask方法取出任务

(6)循环不断调用workerQueue阻塞队列的take方法

(7)任务队列为空就自动阻塞当前线程,直到任务队列不为空唤醒线程去执行任务

5. 线程的工具类

CountDownLatch类

门栓,有时候一个线程的执行需要等待其它线程执行完后再执行

创建:

new CountDownLatch(倒数的数字);

常用方法:

void countDown():倒数一次,数字减一
void await():阻塞当前线程,当倒数为0就唤醒

案例:

public class CountDownLatchDemo {
    public static void main(String[] args) {
        //创建倒数对象
        CountDownLatch latch = new CountDownLatch(3);
        new Thread(() -> {
            System.out.println(Thread.currentThread().getName() + "在等待其它线程!!");
            try {
                //等待其它线程结束
                latch.await();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName() + " finished!!");
        }).start();
        for (int j = 0; j < 3; j++) {
            new Thread(() -> {
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName() + "-->" + i);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                //倒数一次
                latch.countDown();
                System.out.println(Thread.currentThread().getName() + " finished,count=" + latch.getCount());
            }).start();
        }
    }
}

Semaphore 类

信号量,控制启动线程的数量

创建:

new Semaphore(最大数量);

常用方法:

aquired():请求一个信号量
release():释放一个信号量

案例:

public class SemaphoreDemo {
    public static void main(String[] args) {
        //创建信号量
        Semaphore semaphore = new Semaphore(5);
        for (int i = 0; i < 100; i++) {
            //启动线程
            new Thread(() -> {
                try {
                    //请求信号量
                    semaphore.acquire();
                    System.out.println(Thread.currentThread().getName() + "启动了");
                    Thread.sleep(1000);
                    //释放信号量
                    semaphore.release();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值