线程池的五种实现

ThreadPoolExecutor

这个类是JDK中的线程池类,继承自Executor

1、newCachedThreadPool

创建一个线程池,如果线程池中的线程数量过大,它可以有效的回收多余的线程,如果线程数不足,那么它可以创建新的线程。

public class CacheThreadPoolTest {
    private static int counter = 0;
    public static void main(String[] args) throws Exception {
        ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newCachedThreadPool();
        //提交100个任务
        for(int i = 0; i < 1000; i++) {
            //submit()会异常处理 底层-> excute(new Runnable(){})
            threadPool.execute(new Add());
//            threadPool.submit(new Add());
        }
        threadPool.shutdown();
        //打印最多使用线程数
        System.out.println("核心线程数: " +threadPool.getCorePoolSize());
        System.out.println("Largest线程数: " +threadPool.getLargestPoolSize());
        System.out.println("同时执行的Maximum线程数: " +threadPool.getMaximumPoolSize());
        System.out.println(counter);
    }

    static class Add implements Runnable {
        @Override
        public void run() {
            counter++;
        }
    }
}

2、newFixedThreadPool

这种方式可以指定线程池中的线程数。举个栗子,如果一间澡堂子最大只能容纳20个人同时洗澡,那么后面来的人只能在外面排队等待。

public class FixedThreadPoolTest {
    private static int counter = 0;
    public static void main(String[] args) throws Exception {

        ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
        //提交1000个任务
        for(int i = 0; i < 1000; i++) {
            //submit()会异常处理 底层-> excute(new Runnable(){})
            threadPool.submit(new Add());
        }
        threadPool.shutdown();
        //打印最多使用线程数
        System.out.println("核心线程数: " +threadPool.getCorePoolSize());
        System.out.println("Largest线程数: " +threadPool.getLargestPoolSize());
        System.out.println("队列: " +threadPool.getQueue());
        System.out.println("同时执行的Maximum线程数: " +threadPool.getMaximumPoolSize());
        System.out.println(counter);
    }

    static class Add implements Runnable {
        @Override
        public void run() {
            counter++;
        }
    }
}

3、newScheduledThreadPool

该线程池支持定时,以及周期性的任务执行,我们可以延迟任务的执行时间,也可以设置一个周期性的时间让任务重复执行。

定时任务默认是单线程执行,在实际应用场景中可以通过配置 定时任务线程池,实现定时任务并发执行

public class ScheduledThreadPoolTest {
    private static int counter = 0;
    public static void main(String[] args) throws Exception {
        ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newScheduledThreadPool(10);
        //提交1000个任务
        for(int i = 0; i < 1000; i++) {
            //submit()会异常处理 底层-> excute(new Runnable(){})
            threadPool.submit(new Add());
        }
        threadPool.shutdown();
        //打印最多使用线程数
        System.out.println("核心线程数: " +threadPool.getCorePoolSize());
        System.out.println("Largest线程数: " +threadPool.getLargestPoolSize());
        System.out.println("同时执行的Maximum线程数: " +threadPool.getMaximumPoolSize());
        System.out.println(counter);
    }

    static class Add implements Runnable {
        @Override
        public void run() {
            counter++;
        }
    }
}

4、newSingleThreadExecutor

这是一个单线程池,至始至终都由一个线程来执行。

public class SingleThreadPoolTest {
    private static int counter = 0;
    public static void main(String[] args) throws Exception {
        ExecutorService threadPool = Executors.newSingleThreadExecutor();
        //提交1000个任务
        for(int i = 0; i < 1000; i++) {
            //submit()会异常处理 底层-> excute(new Runnable(){})
            threadPool.submit(new Add());
        }
        threadPool.shutdown();
        //打印最多使用线程数
        System.out.println(counter);
    }

    static class Add implements Runnable {
        @Override
        public void run() {
            counter++;
        }
    }

ThreadPoolTaskExecutor

这个类则是spring包下的,是sring为我们提供的线程池类

通过配置类的方式配置线程池,然后注入。(或者spring的配置文件)

1创建线程池

@EnableAsync
@Configuration
public class ExecturConfig {
    @Bean("taskExector")
    public Executor taskExector() {
 
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        int i = Runtime.getRuntime().availableProcessors();//获取到服务器的cpu内核
        executor.setCorePoolSize(10);//核心池大小
        //executor.setMaxPoolSize(100);//最大线程数
        //executor.setQueueCapacity(1000);//队列程度
      //executor.setKeepAliveSeconds(1000);//线程空闲时间
      //executor.setThreadNamePrefix("tsak-asyn");//线程前缀名称
        //executor.setRejectedExecutionHandler(new ThreadPoolExecutor.AbortPolicy());//配置拒绝策略
        return executor;

然后通过自动注入的方式注入线程池

2编写多线程方法

@Resource(name=“taskExecutor”)
ThreadPoolTaskExecutor taskExecutor;
// 或者可以直接@Autowried
@AutoWired
ThreadPoolTaskExecutor taskExecutor

@Component
public class ServerStarter{
    @Async("taskExector")
   public void startServer(){
	//业务逻辑
	}
}

3编写测试调用多线程方法

//测试
public static void main(String[] args) {
	new ServerStarter().startServer();
        }
    }

构造函数中调用,目的就是在类的初始化的时候进行调用。

//实际开发
@Component
public class Server {

    public Server(ServerStarter starter) {
        starter.startServer();
    }
}

手写线程池的几种方式

ThreadPoolTaskExecutor和ThreadPoolExecutor区别

分析下继承关系:
 
 1、ThreadPoolTaskExecutor extends (2)ExecutorConfigurationSupport 
	implements (3)AsyncListenableTaskExecutor, (4)SchedulingTaskExecutor
2、 ExecutorConfigurationSupport extends CustomizableThreadFactory implements BeanNameAware, InitializingBean, DisposableBean 
3、public interface AsyncListenableTaskExecutor extends AsyncTaskExecutor
4、public interface SchedulingTaskExecutor extends AsyncTaskExecutor
从上继承关系可知:
ThreadPoolExecutor是一个java类不提供spring生命周期和参数装配。
ThreadPoolTaskExecutor实现了InitializingBean, DisposableBean ,xxaware等,具有spring特性
AsyncListenableTaskExecutor提供了监听任务方法(相当于添加一个任务监听,提交任务完成都会回调该方法)
简单理解:
1、ThreadPoolTaskExecutor使用ThreadPoolExecutor并增强,扩展了更多特性
2、ThreadPoolTaskExecutor只关注自己增强的部分,任务执行还是ThreadPoolExecutor处理。
3、前者spring自己用着爽,后者离开spring我们用ThreadPoolExecutor爽。
注意:ThreadPoolTaskExecutor 不会自动创建ThreadPoolExecutor需要手动调initialize才会创建
    如果@Bean 就不需手动,会自动InitializingBean的afterPropertiesSet来调initialize

深入线程池,并连环17问

如图两道面试题,顺便深入线程池,并连环17问

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值