JUC-executor线程池

JUC-executor

一:概念

1:Executor(执行者)

Executor是Java里面线程池的顶级接口;

2:ExectorService

继承自Executor的接口,可以看作是Excutor接口功能的扩充,这个接口提供了下面方法;在任务发布以后可以得到一个future对象,从而实现对任务结果的异步获得.

<T> Future<T> submit(Callable<T> var1);

  • 注:execute()方法只能接收Runnable 对象。submit()方法可以接收Runnable和 Callable类型的对象。

  • submit() 方法可以返回持有计算结果的 Future 对象,可以判断任务是否执行成功,而 execute() 方法不可以。

3:ThreadExectorPool

继承了ExecutorService接口,可以看作是以上两个接口的实现类

public ThreadPoolExecutor(
    int corePoolSize, 
    int maximumPoolSize, 
    long keepAliveTime, 
    TimeUnit unit, 
    BlockingQueue<Runnable> workQueue, 
    ThreadFactory threadFactory, 
    RejectedExecutionHandler handler);

二:ThreadExectorPool七个参数

1:corePoolSize

核心线程数,这些线程不会被释放

2:maximumPoolSize

最大线程数,最大可以运行的线程数量

3:keepAliveTime

线程未使用,存活时间,超出核心线程的数量的那些线程,在存活时间内未使用,则释放线程。

4:TimeUnit

keepAliveTime的时间单位,比如分钟,小时等

5:BlockingQueue

缓冲队列,

6:ThreadFactory

线程工厂用来创建新的线程放入线程池

7:RejectedExecutionHandler

线程池拒绝任务的处理策略,比如抛出异常等策略

三:ThreadExectorPool执行流程

1:一个新的线程启动;定义线程池的数量为curSize

2:curSize < corePoolSize,则线程工厂创建核心线程执行;

3:maximumPoolSize > curSizecurSize >= corePoolSize大小,并且缓冲队列未满;则线程进入缓存队列等待核心线程执行。

4:maximumPoolSize > curSize > corePoolSize大小,缓冲队列已满;创建临时线程(超时都会被释放)

5:curSize >= maximumPoolSize则执行拒绝策略。

注:可以想象成银行排队;

取钱的人==线程;

固定开启的窗口==核心线程大小;

等待区等待的人==缓冲队列;

应急窗口+核心窗口==最大线程

一人取钱,常开窗口有空闲的,直接到空闲窗口办理业务;若是没有空闲的,坐在等候区等待;若是等候区也满了,银行立即开启应急窗口,等待的人也可以去应急窗口办理业务;若应急窗口同样满了;银行保安开始执行应急策略,劝退后来者。业务办理完了,人员渐渐没了,应急窗口发现好长时间没有客户来自己窗口,则应急窗口关闭。那些核心窗口无论有没有人都会一直开着。

四:拒绝策略

1:new ThreadPoolExecutor.AbortPolicy()

默认拒绝策略,拒绝任务并抛出任务

2:new ThreadPoolExecutor.CallerRunsPolicy()

使用调用线程的线程直接运行,即哪来的回到哪里;比如main线程开启一个线程调用,若是线程池触发了该拒绝策略,则,这个线程会回归到main线程中执行。

3:new ThreadPoolExecutor.DiscardPolicy()

直接拒绝任务,不抛出错误。

4:new ThreadPoolExecutor.DiscardOldestPolicy()

触发拒绝策略,只要还有任务新增,一直会丢弃阻塞队列的最老的任务,并将新的任务加入

五:代码实现

package com.test.thread;

import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

public class ThreadPoolExecutorTest {

    public static void main(String[] args) {
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5,15,5, TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(3), Executors.defaultThreadFactory(),new ThreadPoolExecutor.CallerRunsPolicy());

        /**
         * 如下:12个任务使用多线程执行
         * 则运行的结果:会有9个线程去执行:5+(12-5-3)=9
         * 解释:
         * 12个任务,超出核心线程但未达到最大线程
         * 因此除去核心线程执行5个任务
         * 加上队列中的等待执行的3个任务,
         * 还有4个任务没有执行12-5-3=4
         * 这时候线程池会开启额外的线程去执行剩余的任务
         * 因此还会开启4个额外线程(5+4<15:不能超过最大线程,超过最大线程,则会执行拒绝策略)
         * 因此执行的任务的线程共计:核心线程5+额外线程4=9个线程;
         */
        for(int i=1;i<=12;i++){
            final int temp = i;
            executor.execute(new Runnable() {
                @Override
                public void run() {
                    System.out.println(Thread.currentThread().getName()+"线程执行");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
        executor.shutdown();
    }
}

六:线程工具

Exectors:jdk提供的线程池工具类。对上面的ThreadExectorPool进行封装。

1:newFixedThreadPool(int nThreads)

public static ExecutorService newFixedThreadPool(int nThreads) 

一种线程数量固定的线程池,当线程处于空闲状态时,他们并不会被回收,除非线程池被关闭。当所有的线程都处于活动状态时,新的任务都会处于等待状态,直到有线程空闲出来

2:newSingleThreadExecutor() 

public static ExecutorService newSingleThreadExecutor() 

创建单个线程。它适用于需要保证顺序地执行各个任务;并且在任意时间点,不会有多个线程是活动的应用场景。

3:newCachedThreadPool() 

public static ExecutorService newCachedThreadPool()

创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。

存在三个任务a,b,c。线程池创建线程1用于执行任务a,如果a任务执行完后,任务c尚未执行,则线程1将用于执行任务c。

4:newScheduledThreadPool(int corePoolSize)

public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) 

创建一个线程池,可以调度命令在给定的延迟之后运行,或定期执行, 支持执行定时性或周期性任务。

5:newWorkStealingPool(int parallelism)

public static ExecutorService newWorkStealingPool(int parallelism) 

顾名思义,它基于 工作窃取算法,其中任务可以生成其他较小的任务,这些任务将添加到并行处理线程的队列中。如果一个线程完成了工作并且无事可做,则可以从另一线程的队列中“窃取”工作。

真正意义上的并行,只要有活着的线程,就会让空闲的CPU内核去执行。而不是传统多线程的逻辑意义上的并行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值