Java基础之线程池

Java基础之线程池

1、SingleTHreadExecutor 单线程线程池

  • 源码
public static ExecutorService newSingleThreadExecutor() {
    return new FinalizableDelegatedExecutorService
        (new ThreadPoolExecutor(1, 1,
                                0L, TimeUnit.MILLISECONDS,
                                new LinkedBlockingQueue<Runnable>()));
}
public static void main(String[] args) {
    // 特点:
    // 1、核心线程和最大线程都是1
    // 2、阻塞队列是无界的,可以存放任意数量的任务
    ExecutorService singleThreadExecutor= Executors.newSingleThreadExecutor();
    for(int i=0;i<10;i++){
        int index=i;
        singleThreadExecutor.execute(()->{
            try{
                Thread.sleep(1000);
                System.out.println(Thread.currentThread().getName()+"线程:"+index);
            }catch (Exception e){
                e.printStackTrace();
            }
        });
    }
}

测试结果

pool-1-thread-1线程:0
pool-1-thread-1线程:1
pool-1-thread-1线程:2
pool-1-thread-1线程:3
pool-1-thread-1线程:4
pool-1-thread-1线程:5
pool-1-thread-1线程:6
pool-1-thread-1线程:7
pool-1-thread-1线程:8
pool-1-thread-1线程:9

2、CachedThreadPool 缓存线程池

  • 源码
public static ExecutorService newCachedThreadPool() {
    return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                  60L, TimeUnit.SECONDS,
                                  new SynchronousQueue<Runnable>());
}
特点:
    核心线程:0
    最大线程:Integer的最大值
    队列:SynchronnousQueue
可以创建多个线程,最大线程不受限制,来一个任务,就会创建一个线程去执行它,任务不会等待,线程的最大保持时间为60秒。
public static void main(String[] args) {
    // 带缓存线程池
    ExecutorService cachedThreadPool= Executors.newCachedThreadPool();

    for(int i=0;i<10;i++){
        int index=i;
        cachedThreadPool.execute(()->{
            System.out.println(Thread.currentThread().getName()+"::"+index);
        });
    }
    cachedThreadPool.shutdown();// 关闭
}

执行结果

pool-1-thread-1::0
pool-1-thread-4::3
pool-1-thread-3::2
pool-1-thread-2::1
pool-1-thread-6::5
pool-1-thread-5::4
pool-1-thread-7::6
pool-1-thread-8::7
pool-1-thread-9::8
pool-1-thread-2::9

3、FixedThreadPool 固定线程池

  • 源码
public static ExecutorService newFixedThreadPool(int nThreads) {
    return new ThreadPoolExecutor(nThreads, nThreads,
                                  0L, TimeUnit.MILLISECONDS,
                                  new LinkedBlockingQueue<Runnable>());
}
特点:
    核心线程和最大线程数一样
public static void main(String[] args) {
        // 固定线程池
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(4);
        for(int i=0;i<10;i++){
            int index=i;
            fixedThreadPool.execute(()->{
                System.out.println(Thread.currentThread().getName()+"::"+index);
            });
        }
        fixedThreadPool.shutdown();// 关闭
}
  • 运行结果
pool-1-thread-3::2
pool-1-thread-2::1
pool-1-thread-4::3
pool-1-thread-1::0
pool-1-thread-4::6
pool-1-thread-3::4
pool-1-thread-2::5
pool-1-thread-3::9
pool-1-thread-4::8
pool-1-thread-1::7

4、ScheduledThreadPool

public static void main(String[] args) {
    
    ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(2);// 设置核心线程的个数
    for(int i=0;i<10;i++){
        int index=i;
        Runnable task=new Runnable() {
            @Override
            public void run() {
                System.out.println(new Date().toString()+":"+ Thread.currentThread().getName()+"执行了"+index);
            }
        };
        // 让线程任务等待i秒后在执行
        ScheduledFuture<?> schedule=scheduledExecutorService.schedule(task,i, TimeUnit.SECONDS);
    }
    scheduledExecutorService.shutdown();
}

测试结果

Wed Aug 11 22:33:25 CST 2021:pool-1-thread-1执行了0
Wed Aug 11 22:33:26 CST 2021:pool-1-thread-2执行了1
Wed Aug 11 22:33:27 CST 2021:pool-1-thread-1执行了2
Wed Aug 11 22:33:28 CST 2021:pool-1-thread-2执行了3
Wed Aug 11 22:33:29 CST 2021:pool-1-thread-1执行了4
Wed Aug 11 22:33:30 CST 2021:pool-1-thread-2执行了5
Wed Aug 11 22:33:31 CST 2021:pool-1-thread-1执行了6
Wed Aug 11 22:33:32 CST 2021:pool-1-thread-2执行了7
Wed Aug 11 22:33:33 CST 2021:pool-1-thread-1执行了8
Wed Aug 11 22:33:34 CST 2021:pool-1-thread-2执行了9

5、自定义线程池

源码

public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              RejectedExecutionHandler handler) {
        this(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
             Executors.defaultThreadFactory(), handler);
    }
参数介绍:
    corePoolSize: 核心线程数
    maximumPoolSize: 最大线程数
    keepAliveTime: 线程保持连接时间
    TimeUnit: 线程保持连接时间的单位
    BlockingQueue<Runnable>: 线程任务队列
    RejectedExecutionHandler: 拒绝策略
public static void main(String[] args) {

    // 创建一个线程池:固定大小线程池
    // 自定义一个线程池
    // 默认拒绝策略
    //     任务无法处理时,会抛出异常RejectedExecutionException,不再执行这个任务
    ExecutorService executor=  new ThreadPoolExecutor(3,3,0, TimeUnit.SECONDS,
                                                      new LinkedBlockingDeque<>(1),new ThreadPoolExecutor.AbortPolicy());

    for(int i=0;i<10;i++){
        int index=i;
        executor.execute(()->{
            System.out.println(Thread.currentThread().getName() +
                               " 执行了第 " + index + " 个任务");
            try{
                Thread.sleep(1000);
            }catch (Exception e){
                e.printStackTrace();
            }
        });
    }
    executor.shutdown();// 关闭线程池
}

运行结果

pool-1-thread-2 执行了第 1 个任务
pool-1-thread-3 执行了第 2 个任务
pool-1-thread-1 执行了第 0 个任务
Exception in thread "main" java.util.concurrent.RejectedExecutionException: Task com.baizhou.test.test01.Test03$$Lambda$1/548246552@5010be6 rejected from java.util.concurrent.ThreadPoolExecutor@685f4c2e[Running, pool size = 3, active threads = 3, queued tasks = 1, completed tasks = 0]
	at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2047)
	at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:823)
	at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1369)
	at com.baizhou.test.test01.Test03.main(Test03.java:17)
pool-1-thread-1 执行了第 3 个任务

原因:keepAliveTime设置为0秒,每个线程执行完毕后都会被销毁,队列中只能保存一个任务,多余的任务被拒绝策略处理

拒绝策略

1、AbortPolicy

默认拒绝策略
任务无法处理时,会抛出异常RejectedExecutionException,不再执行这个任务

2、CallerRunsPolicy

如果线程池没有shutdown,则调用execute函数的上层线程(main)去执行被拒绝的任务

3、DiscardOldsetPolicy

将任务队列中最老的任务丢弃(快要被执行的任务),尝试再次提交新任务

4、DiscardPolicy

直接丢弃这个无法处理的任务

5、自定义策略

1、实现RejectedExecutionHandler接口
2、重写接口中的rejectedExecutor方法	
posted @ 2021-08-11 23:52  黎白昼  阅读(55)  评论(0)    收藏  举报