线程池

什么是线程池?

1、线程池是一个线程容器,可以设置线程分配的数量上限。

2、将预先创建的线程对象放入线程池,并重用线程池中的线程对象。

3、避免频繁的创建和销毁线程。

为什么使用线程池?

1、线程是宝贵的内存资源,单个线程约占1MB空间,过多分配容易造成内存溢出。

2、频繁的创建、销毁线程会增加虚拟机回收频率、资源开销,造成程序性能下降。

线程池工作原理

将任务提交给线程池,由线程池分配线程、运行任务,并在当前任务结束后复用线程。

常用的线程池接口和类(所在包 java.util.concurren)

 

Executor:线程池的顶级接口。

ExecutorService:线程池接口,继承了Executor,并新增了一些用于任务提交及管理的一些方法,例如任务的提交、任务的停止等。

ThreadPoolExecutor:线程池中最核心的一个类,继承了AbstractExecutorService,它是线程池最具体的实现,因为它实现了Executor中所定义的execute ()方法。

ScheduledThreadPoolExecutor:可以实现定时任务的线程池。

Executors:通过此类可以帮助我们创建线程池:

  1、newCachedThreadPool:创建一个可缓存的线程池,线程的数量根据我们传入的任务数量发生改变。

  2、newFixedThreadPool:创建一个定长的线程池,可控制最大并发量。

  3、newScheduledThreadPool:创建一个定长的线程池,可用于指定定时或周期任务。

  4、newSingleThreadPool:创建一个单线程的线程池,它只会用唯一的工作线程来执行任务。

注:

线程池不允许使用Executors去创建,而要通过ThreadPoolExecutor方式。

这一方面是由于jdk中Executor框架虽然提供了如newFixedThreadPool()、newSingleThreadExecutor()、newCachedThreadPool()等创建线程池的方法,但都有其局限性,不够灵活;

另外由于前面几种方法内部也是通过ThreadPoolExecutor方式实现,使用ThreadPoolExecutor有助于大家明确线程池的运行规则,创建符合自己的业务场景需要的线程池,避免资源耗尽的风险。

 

代码演示:

public static void main(String[] args) {
        //创建定长线程池,指定线程池最大线程数为4
//        ExecutorService executorService = Executors.newFixedThreadPool(4);
        //创建带缓存的线程池,线程池线程数由任务数决定
//        ExecutorService executorService = Executors.newCachedThreadPool();
        //创建一个单线程线程池
//        ExecutorService executorService=Executors.newSingleThreadExecutor();
        //创建一个支持定时、周期任务的线程池
        ExecutorService executorService = Executors.newScheduledThreadPool(8);
        //定义任务
        Runnable task = new Runnable() {
            //定义票的总量100张
            private int ticket = 100;

            @Override
            public void run() {
                while (true) {
                    if (ticket == 0) {
                        break;
                    }
                    System.out.println(Thread.currentThread().getName() + "售出第" + ticket + "张票");
                    ticket--;
                }
            }
        };
        //提交任务。这里提交4次代表创建4个线程去执行任务
        for (int i = 0; i < 4; i++) {
            executorService.submit(task);
        }

        //关闭线程池
        executorService.shutdown();//当线程池中的任务全部执行完毕后,才会执行关闭操作

        executorService.shutdownNow();//立即关闭线程池,可能会造成任务执行异常
    }

 

posted @ 2022-12-28 03:52  Amireux-126  阅读(23)  评论(0)    收藏  举报