为什么要使用线程池,线程池如何创建?

在了解为什么使用线程池之前我们先回顾下Java创建线程的几种方式。

第一种,继承Thread类

    /**
     * 线程使用方法一:继承Thread类重写run方法,通过start方法开始调用
     */
    public static class Thread01 extends Thread{
        @Override
        public void run() {
            System.out.println("Thread01线程开始执行...");
            int res = 10 / 2;
            System.out.println("Thread01线程执行完毕,结果:" + res);
        }
    }

第二种,实现Runnable接口

/**
     * 线程用法二:实现Runnable接口,通过new Thread时传入
     */
    public static class Runnable01 implements Runnable{
        @Override
        public void run() {
            System.out.println("Runnable01线程开始执行...");
            int res = 10 / 2;
            System.out.println("Runnable01线程执行完毕,结果:" + res);
        }
    }

第三种,使用Callable接口


public static void main(String[] args) throws ExecutionException, InterruptedException {

        System.out.println("main....start");

        // Callable
        FutureTask futureTask = new FutureTask<>(new Callable01());
        new Thread(futureTask).start();
    
        // 此时没有体现出Callable最大的好处,主线程main还是提前与异步线程,于是我们可以通过
        // get方法,阻塞线程实现获取返回值
        Integer integer = (Integer) futureTask.get();

        System.out.println("main...end:" + integer);

    }


/**
     * 线程使用方法三:使用Callable接口,Callable接口与Thread和Runnable接口不同的是
     * Callable接口拥有返回值,可与FutureTask实现异步获取返回值
     */
    public static class Callable01 implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            System.out.println("Callable01线程开始执行...");
            int res = 10 / 2;
            System.out.println("Callable01线程执行完毕,结果:" + res);
            return res;
        }
    }

但是无论使用哪种方式创建线程,在我们的业务系统中如此操作必然会造成系统资源难以管理,于是线程池的概念就应运而生,在庞大的业务系统中,任何的线程操作都应该交由线程池来管理,大家都应该把自己的任务交给线程池,由线程池来代理运行。

public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start");
        
        // 在业务代码中,随时创建线程是大忌,我们可以采用线程池的方式来管理线程

        // 创建一个有10个线程的线程池
        ExecutorService service = Executors.newFixedThreadPool(10);
        // 分配一个任务,由其执行
        service.execute(new Runnable01());

        System.out.println("main...end:");

    }

这种方式则是使用了Executors工具类帮我们创建线程池,我们可以看下如何使用原生的方法去创建线程池。

public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start");

        /**
         * 最多拥有七个参数:
         * corePoolSize:核心线程数,指线程池创建完成后系统中就已经存在的线程数,就等待来接收异步任务
         * maximumPoolSize:最多存在的线程数,用于控制资源并发
         * keepAliveTime:当线程数量大于核心数量,空闲线程等待接收新任务的时间,超时即销毁
         *                需要释放的线程数=maximumPoolSize-maximumPoolSize
         * unit:时间单位
         * BlockingQueue<Runnable> workQueue:阻塞队列,如果任务有很多无法处理,多余任务将会在此等待处理。
         * threadFactory:线程工厂,一般不用改
         * RejectedExecutionHandler handler:如果队列满了,按照我们指定的策略拒绝执行任务。
         */
        ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 20, 10,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(10000), // 指定最多的等待任务,超出即拒绝执行
                Executors.defaultThreadFactory(), // 使用默认的线程工厂,此参数可省略
                new ThreadPoolExecutor.AbortPolicy()
                );

        System.out.println("main...end:");

但是以上都可以使用Executors工具类来实现创建:

public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main....start");
        // 缓存线程池
        ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
        // 创建固定线程数的线程池
        ExecutorService executorService = Executors.newFixedThreadPool(200);
        // 创建支持任务调度的线程池
        ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(100);
        // 创建单线程线程池,从队列里面获取任务,依次执行
        ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
        
        System.out.println("main...end:");

    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值