线程池的执行机制

什么是线程池

java程序创建的线程称为用户线程,但在工作过程中最终是通过一个核心线程来完成对操作系统硬件的使用,在这个过程中就涉及到了内核线程和核心线程的交互,当大量的用户线程参与进工作当中,就会影响性能。同时频繁的创建和销毁用户线程也会影响性能,因此线程池出现了,线程池可以管理和重复利用线程,有效地管理多个线程,提高线程的利用率和系统的性能。

线程池的参数:

  1. 核心线程数 : 线程数的底线,在没有到达底线前, 新任务会创建新线程

  2. 等待队列: 当核心数量的线程都处于工作状态,新任务会存入队列

  3. 最大线程数: 线程数的上限

  4. 空闲线程等待时间数 

  5. 空闲线程等待时间单位 

  6. 线程工厂: 创建线程的。 juc提供了默认的线程工厂。 也可以自定义线程工厂

  7. 拒绝策略:线程已满且都在忙碌,队列已满。新任务将被决绝。

    juc中提供了一些默认的拒绝策略,也可以自定义拒绝策略

线程池的执行机制:

任务进入线程池中,如果当前工作的线程少于核心线程数量,则创建新的核心线程来执行任务,否则尝试加入等待队列,如果等待队列中的任务未满,则加入等待队列等待空闲线程来执行任务,反之则判断线程数是否达到上限,如果没有则创建新线程执行任务,反之则触发拒绝策略。执行完任务的线程并不会马上销毁,而是尝试去等待队列查找任务,若队列中没有任务,则线程进入等待状态,超过等待时间的线程则被销毁,但默认会保留核心线程。

如何创建线程池:

ThreadPoolExecutor poolExecutor1= new ThreadPoolExecutor(2,5,
                                                               30, TimeUnit.SECONDS,
                                                                new ArrayBlockingQueue<>(5));

例如上述代码,我们创建了一个名为poolExecutor1的线程池,参数列表依次为核心线程数(2),线程最大数(5),线程等待时间(30),线程等待时间单位(秒),阻塞队列(大小为5)

线程池常用方法:

 执行线程:

pool.execute(runnable对象);

Runnable r=()-> {
               System.out.println(Thread.currentThread().getName()+"正在执行");
               try {
                   Thread.sleep(2000);
               } catch (InterruptedException e) {
                   throw new RuntimeException(e);
               }
               System.out.println(Thread.currentThread().getName()+"执行完毕");
       };
       poolExecutor1.execute(r);

 获得等待队列:

BlockingQueue<Runnable> queue = pool.getQueue();

 获得队列中等待任务的数量:

queue.size();

 获得线程池中线程的数量:

pool.getPoolSize();

 允许所有的空闲线程都回收,不考虑核心线程数量:

pool.allowCoreThreadTimeOut();

 线程池启动时就创建核心数量的线程:

pool.prestartAllCoreThread();

阻塞队列:

JUC提供了一些常用的阻塞队列:

  • ArrayBlockingQuery : 底层是Array,创建时必须指定大小

  • LinkedBlockingQuery: 底层是链表,可以长短,也可以不知道,可以作为无限队列

  • PriorityBockdingQuery : 自然队列,底层使用的堆来存,自然有序(有大小)

    可以控制任务执行的先后顺序

    给任务设置优先级

  • DelayQuery : 延迟队列,可以延迟执行任务,可以定时执行任务

线程工厂:

JUC提供了默认的线程工厂 :

Executors.defaultThreadFactory()

  自定义线程工厂:

public class MyThreadFactory implements ThreadFactory {
    static final String pool_prefix  = "user-pool";
    static String thread_prefix = "thread" ;
    static int thread_index = 1;
    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(r);
        //user-pool-thread-1
        t.setName(pool_prefix+"-"+thread_prefix+"-"+thread_index);
        thread_index ++ ;
        return t ;
   
    }
}

上述代码我们是自定义线程名称的一个线程工厂

拒绝策略:

juc提供了4种拒绝策略:

1.AbortPolicy : 拒绝任务,并给出异常提示

2.DiscardPolicy : 拒绝任务,没有提示

3.DiscardOldestPolicy : 拒绝最早加入队列的任务

4.CallerRunsPolicy:拒绝任务,交给任务的发起者来执行

我们也可以自定义拒绝策略。

  • 9
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值