线程池的学习

线程池

使用原始方式创建线程

继承Thread类

    public static void main(String[] args) {
        System.out.println("main-----start-----");
        new User().start();
        System.out.println("main-----end-------");
    }
    private static class User extends Thread{
        @Override
        public void run() {
            System.out.println("使用继承Thread方式开启线程");
        }
    }

实现Runnable接口

    public static void main(String[] args) {
        System.out.println("main-----start-----");
        User user= new User();
        new Thread(user).start();
        System.out.println("main-----end-------");
    }
    private static class User implements Runnable{
        @Override
        public void run() {
            System.out.println("使用实现Runnable接口开启线程");
        }
    }

实现Callable接口 + FutureTask (可以拿到返回结果,可以处理异常)

    public static void main(String[] args) throws ExecutionException, InterruptedException {
        System.out.println("main-----start-----");
        FutureTask<Integer> integerFutureTask = new FutureTask<>(new User());
        new Thread(integerFutureTask).start();
        Integer integer = integerFutureTask.get();
        System.out.println(integer);
        System.out.println("main-----end-------");
    }
    private static class User implements Callable<Integer> {
        @Override
        public Integer call() throws Exception {
            System.out.println("实现Callable接口创建线程");
            return 10;
        }
    }

总结:以上三种开启线程的方式在程序中都不推荐使用,如果这样创建线程就好比公司有活了就招一个人,没活了就开除,之后有活了又招i 一个人,显然是不合理的,如果有100万请求同时访问一个接口,这个接口一次又会开一个线程跑程序,就是有100万个线程同时进行。这时候我们就需要使用线程池

线程池

使用线程池的优点

  1. 统一管理资源
  2. 更快速的执行任务,不需要每次创建线程销毁线程消耗时间,免去了系统资源的开销
  3. 如果不使用线程池,有可能会创建大量的线程导致消耗完系统内存

四大线程池

  1. Executors.newFixedThreadPool(size)
    创建一个固定大小的线程池,核心线程与最大线程与设置的一致,阻塞队列的大小是Integer的最大值
  2. Executors.newSingleThreadExecutor()
    创建只有一个线程的线程池,核心线程与最大线程都是1,阻塞队列的大小是Integer的最大值
  3. Executors.newCachedThreadPool()
    创建一个有缓存的线程池,没有核心线程,最大线程为Integer的最大值,线程空闲60s自动销毁
  4. Executors.newScheduledThreadPool(10)
    创建一个定长线程池,支持定时及周期性任务执行

自定义线程池

 ThreadPoolExecutor executor = new ThreadPoolExecutor(
 10,
 20,
 60,
 TimeUnit.SECONDS,
 new LinkedBlockingQueue<Runnable>(),
 Executors.defaultThreadFactory(),new ThreadPoolExecutor.CallerRunsPolicy());

参数一(corePoolSize): 线程池的核心线程,表示就算空闲也不会被销毁,在第一次使用使用线程池创建
参数一(maximumPoolSize): 线程池的最大线程,表示还可以创建maximumPoolSize-corePoolSize的线程数量
参数三(keepAliveTime): maximumPoolSize-corePoolSize的线程空闲多久销毁线程
参数四(unit): 时间单位
参数五(workQueue): 阻塞队列,线程满了之后任务到队列中等待
参数六(threadFactory) : 线程的创建工厂
参数七(handler): 当核心线程满了,队列中也满了,最大线程也满了,将使用拒绝策略拒绝任务
拒绝策略:
1. AbortPolicy:默认策略,在需要拒绝任务时抛出RejectedExecutionException
2. CallerRunsPolicy:直接在 execute 方法的调用线程中运行被拒绝的任务,如果线程池已经关闭,任务将被丢弃;
3. DiscardPolicy:直接丢弃任务
4. DiscardOldestPolicy:丢弃队列中等待最长的任务,执行当前任务,如果线程池已经关闭,任务将被丢弃

工作顺序

当有任务时,首先会使用核心线程去执行,核心线程满了之后任务会进去阻塞队列中等待,当阻塞队列也满了之后,将会开启线程执行任务,当任务空闲指定之间之后将会被销毁,如果最大线程也满了之后则会使用拒绝策略拒绝任务
例:核心线程:3,最大线程20,阻塞队列大小:50。 现在有100个任务怎么分配?
首先会让3个核心线程执行3个任务,50个任务进入阻塞队列,再创建17个线程执行任务,拒绝30个任务(不考虑执行完成之后再取任务)

推荐使用

阿里巴巴规范手册中禁止使用Executors去创建线程池
原因:newFixedThreadPool和newSingleThreadExecutor: 主要问题是堆积的请求处理队列可能会耗费非常大的内存,甚至OOM
newCachedThreadPool和newScheduledThreadPool: 主要问题是线程数最大数是Integer.MAX_VALUE,可能会创建数量非常多的线程,甚至OOM。
推荐使用ThreadPoolExecutor创建线程池
例:

    @Bean("asyncExecutor")
    public Executor asyncServiceExecutor() {
        log.info("start asyncServiceExecutor");
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        //配置核心线程数
        executor.setCorePoolSize(5);
        //配置最大线程数
        executor.setMaxPoolSize(5);
        //配置队列大小
        executor.setQueueCapacity(99999);
        //配置线程池中的线程的名称前缀
        executor.setThreadNamePrefix("async-service-");

        // rejection-policy:当pool已经达到max size的时候,如何处理新任务
        // CALLER_RUNS:不在新线程中执行任务,而是有调用者所在的线程来执行
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        //执行初始化
        executor.initialize();
        return executor;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值