关于线程池你了解些什么?

前言

学习线程池的思维导图

关于线程池你了解些什么?_第1张图片

  1. 线程池是什么?它有什么用?

虽然线程比进程更轻量级,但是每个进程所占的资源空间是有限,如果我们频繁创建和销毁线程也会消耗很多CPU资源,那么我们该如何解决这个问题呢?

官方解释:线程池是一种多线程处理形式,其处理过程可以将多个任务添加到阻塞队列中,在创建线程后自动启动这些任务.简单来说,线程池就是提前准备好线程,我们创建线程可以直接在线程池中去拿,用完了还给线程池.这样会比从系统中申请更高效吗?答案是会的,因为我们直接从线程池中取线程是纯用户态(更及时一些)操作,而从系统申请涉及到内核态(不一定及时)的操作.通俗点来说,新开业的店一个人都没有,如果来一个客人雇一个员工去服务,服务完再解雇,重复雇佣再解雇会浪费大量时间,所以我们可以选择先规定一个固定员工人数,客人很多的时候,当店里没有达到固定员工人数再去雇佣人员,否则达到了固定员工人数,我们就将客人的信息记录下来,等哪个员工闲下来就让哪个员工去服务,如果是淡季没有什么客人来,就可以根据时间和客流量适当辞掉一部分员工,这样就提高了效率.


  1. 原装的线程池对象的构造

ThreadPoolExecutor类(原装线程池类),根据jdk文档我们选择参数最长的ThreadPoolExecutor构造方法,如下:

关于线程池你了解些什么?_第2张图片

● corePoolSize 核心线程数 (固定线程数)

● maxmumPoolSize 最大线程数 (固定线程数+临时线程)

● keepAliveTime 不忙的时候,临时线程能存活的最大时间

● TimeUnit unit 不忙的时候,临时线程能存活最大时间的单位

● BlockingQueue workQueue 组织线程池任务的阻塞队列

● ThreadFactory threadFactory 创建线程的辅助类

● RejectedExecutionHandler handler 线程池的拒绝策略(线程池满了该如何拒绝?)

四种拒绝策略

① ThreadPoolExecutor.AbortPolicy 直接罢工抛异常

② ThreadPoolExecutor.CallerRunsPolicy 谁添加的任务谁执行

③ ThreadPoolExecutor.DiscardOldestPolicy 丢弃最老任务(阻塞队列队首任务)

④ ThreadPoolExecutor.DiscardPolicy 丢弃最新添加的这个任务

关于线程池你了解些什么?_第3张图片

  1. 使用Executors类完成线程池的四种创建方式

Executors是一个工厂类,辅助线程池对象创建,它是ThreadPoolExecutor类(原装线程池类)的封装,我们使用它的四个类方法去实现线程池的创建.

① newFixedThreadPool() 方法创建的是固定线程数的线程池.

② newCachedThreadPool() 方法创建线程数目动态增长的线程池.

③ newSingleThreadExecutor() 方法创建只包含单个线程的线程池.

④ newScheduledThreadPool() 方法设定延迟时间后的执行命令,或者定期执行命令.

注:以ExecutorService es = Executors.四种方法 就能创建不同特点的线程池了.


  1. 如何实现一个固定线程数的线程池

class MyExecutorService {
    BlockingQueue queue = new LinkedBlockingQueue<>();

    public void submit(Runnable runnable) throws InterruptedException {
        queue.put(runnable);
    }

    public  MyExecutorService(int n) {
        for (int i = 0; i < n; i++) {
            Thread thread = new Thread(() -> {
                while (true) {
                    try {
                        Runnable runnable = queue.take();
                        runnable.run();
//                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            thread.start();
        }
    }
}

public class ThreadDemoTest6 {
    static Object object = new Object();
    public static void main(String[] args) throws InterruptedException {

//        ExecutorService executorService = Executors.newFixedThreadPool(10);
//        executorService.submit(new Runnable() {
//            @Override
//            public void run() {
//                System.out.println();
//            }
//        });

        //简易实现:创建固定线程数为10个的线程池
        MyExecutorService service = new MyExecutorService(10);
        for (int i = 0; i < 1000; i++) {
            int num = i;
            service.submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println(num);
                }
            });
        }
    }
}

一千个任务由固定十个线程去完成,而不是创建一千个线程去执行对应一个任务.节省了创建和销毁线程.

关于线程池你了解些什么?_第4张图片

注:这里没有实现工厂模式,工厂模式用于解决构造方法带来的问题(一个类中,两种或多种构造方法的实现不同,但是参数相同),工厂模式就单独实现一个工厂类,去实现静态的普通方法去辅助对象的构造.


分享完毕~

你可能感兴趣的:(Java,jvm)