线程池 - 重点(Juc-06)

本贴最后更新于 1243 天前,其中的信息可能已经事过景迁

简单介绍

线程池:三大方法、七大参数、四种拒绝策略

程序的运行,本质:占用系统资源!优化资源的使用!=> 池化技术

线程池、连接池、内存池、对象池

池化技术:事先准备好一些资源,有人要用,就来我这里拿,用完之后还给我,下个人再用

线程池的好处

  1. 降低资源的消耗
  2. 提高响应的速度
  3. 方便管理

一句话总结:线程可以复用,控制最大并发数,管理线程

三大方法

阿里开发手册中这样讲

image.png

package net.yscxy.pool;


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

/**
 * @Author WangFuKun
 * @create 2020/11/21 21:05
 */
/*
 * Executors 工具类
 * 使用了线程池之后,需要使用线程池来创建线程
 * */
public class Demo01 {

    public static void main(String[] args) {
        //ExecutorService executorService = Executors.newSingleThreadExecutor(); //单个线程
        // ExecutorService executorService = Executors.newFixedThreadPool(5);    //创建一个固定的线程池的大小
        ExecutorService executorService = Executors.newCachedThreadPool();       //可以伸缩的,遇强则强,遇弱则弱
        try {
            for (int i = 0; i < 100; i++) {
                executorService.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + "——>OK");
                });
            }
            //线程池用完程序结束关闭线程池
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            executorService.shutdown();
        }
    }

}

七大参数

源码分析

 public static ExecutorService newSingleThreadExecutor() {
        return new FinalizableDelegatedExecutorService
            (new ThreadPoolExecutor(1, 1,
                                    0L, TimeUnit.MILLISECONDS,
                                    new LinkedBlockingQueue<Runnable>()));
    }
public static ExecutorService newFixedThreadPool(int nThreads) {
        return new ThreadPoolExecutor(nThreads, nThreads,
                                      0L, TimeUnit.MILLISECONDS,
                                      new LinkedBlockingQueue<Runnable>());
    }
 public static ExecutorService newCachedThreadPool() {
        return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
                                      60L, TimeUnit.SECONDS,
                                      new SynchronousQueue<Runnable>());
    }

本质:ThreadPoolExecutor(),因为这三个方法都调用的这个方法

public ThreadPoolExecutor(int corePoolSize, //核心线程池大小
                              int maximumPoolSize,//最大核心线程池大小
                              long keepAliveTime,//超时了没有人调用就会释放
                              TimeUnit unit,//超时单位
                              BlockingQueue<Runnable> workQueue,//阻塞队列
                              ThreadFactory threadFactory,//线程工厂,创建线程用,一般不用懂
                              RejectedExecutionHandler handler//拒绝策略) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.acc = System.getSecurityManager() == null ?
                null :
                AccessController.getContext();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

四种拒绝策略(自定义)

image.png

new ThreadPoolExecutor.AbortPolicy() 队列满了,还有人进来,不处理这个人的,抛出异常
new ThreadPoolExecutor.CallerRunsPolicy() 队列满了了的话哪里来的,去哪里,也就是让main线程去执行这个
new ThreadPoolExecutor.DiscardOldestPolicy() 队列满了就不处理,但是不会抛出异常 
new ThreadPoolExecutor.DiscardOldestPolicy() 队列满了,尝试和最早的竞争,但是不会抛出异常

代码

package net.yscxy.pool;

import java.util.concurrent.*;

/**
 * @Author WangFuKun
 * @create 2020/11/22 17:31
 */
/*
 * new ThreadPoolExecutor.AbortPolicy() 队列满了,还有人进来,不处理这个人的,抛出异常
 * new ThreadPoolExecutor.CallerRunsPolicy() 队列满了了的话哪里来的,去哪里,也就是让main线程去执行这个
 * new ThreadPoolExecutor.DiscardOldestPolicy() 队列满了就不处理,但是不会抛出异常
 * new ThreadPoolExecutor.DiscardOldestPolicy() 队列满了,尝试和最早的竞争,但是不会抛出异常
 * */
public class Demo02 {
    public static void main(String[] args) {
        //自定义线程池
        ExecutorService executor = new ThreadPoolExecutor(
                2,
                5,
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<Runnable>(3),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.DiscardOldestPolicy());//队列满了,尝试和最早的竞争,但是不会抛出异常
        try {
            for (int i = 0; i < 20; i++) {
                executor.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + "——>OK");
                });
            }
            //线程池用完程序结束关闭线程池
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            executor.shutdown();
        }
    }
}

最大线程池到底应该如何定义

1.cpu 密集型,几核就是几,可以保持 cpu 效率最高
2.IO 密集型 判断程序中十分消耗 IO 的线程
如果程序 :15 个大型任务,io 十分占用资源 ,那就设置为两倍
获取 cpu 的最大核心数

Runtime.getRuntime().availableProcessors()
  • JUC
    17 引用 • 3 回帖 • 1 关注
1 操作
yscxy 在 2020-11-23 14:45:19 更新了该帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...