使用ThreadPoolExecutor手动创建线程池+线程池工具类+使用线程池

本文介绍了如何使用自定义线程池工具类创建线程池,包括线程工厂的自定义实现,以及在Spring应用中通过注入管理线程池的示例。还讨论了使用ThreadPoolExecutor的策略,如线程池大小、拒绝策略等。
摘要由CSDN通过智能技术生成


前言

1.之前简单的说过使用ThreadPoolExecutor创建线程池是优于使用Executors创建线程池,链接:ThreadPoolExecutor手动创建线程池优于Executors类
2.下面内容中会涉及到线程池的拒绝策略,这里可以阅读其他作者的文章,链接拒绝策略


一、线程池工具类

自定义实现JAVA线程池的线程工厂类——ThreadFactory:Java提供了ThreadFactory接口,用于创建你自己的线程对象工厂,可以设置线程名称、优先级等属性。(这里我只设置了线程名称,其他的大家自己探索)

public class ThreadPoolUtils {

	public static ExecutorService createExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
			TimeUnit unit, int queueSize, String name) {
		return new ThreadPoolExecutor(corePoolSize, maximumPoolSize, keepAliveTime, unit,
				new LinkedBlockingQueue<>(queueSize), new NamedThreadFactory(name),
				new ThreadPoolExecutor.CallerRunsPolicy());
	}

	public static ExecutorService singleExecutor(String name, RejectedExecutionHandler handler) {
		return new ThreadPoolExecutor(1, 1, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(2),
				new NamedThreadFactory(name), handler);
	}
	/**
	 * 自定义实现JAVA线程池的线程工厂类
	 * 自定义具有描述意义的线程名称。如果使用默认的ThreadFactory,它给线程起名字大概规律就是pool-m-thread-n,但是当你分析一个thread dump时,看着这样的名字就很难知道线程的目的。所以使用一个有描述意义的线程名称是分析追踪问题的关键。
	 * 设置线程是否是守护线程,默认的ThreadFactory总是提交非守护线程
	 * 设置线程优先级,默认ThreadFactory总是提交的一般优先级线程
	 */
	public static class NamedThreadFactory implements ThreadFactory {

		private final String namePrefix;
		private final AtomicInteger nextId = new AtomicInteger(1);

		public NamedThreadFactory(String prefix) {
			this.namePrefix = prefix + "-";
		}

		@Override
		public Thread newThread(Runnable r) {
			String name = namePrefix + nextId.getAndIncrement();
			return new Thread(null, r, name);
		}

	}
}

二、使用工具类中的线程池

	private ExecutorService sigleThreadExecutor = ThreadPoolUtils.singleExecutor("test",new ThreadPoolExecutor.CallerRunsPolicy());
	public void test(){
	
	List<String> list = new ArrayList<>();
	// 记录单个任务的执行次数
    CountDownLatch countDownLatch = new CountDownLatch(list .size());
	
	for(String str : list){
	
		sigleThreadExecutor.execute(() ->{
		//这里编写要处理的方法
		 System.out.println(str);
		 
		// 任务个数 - 1, 直至为0时唤醒await()
		countDownLatch.countDown();
	
		});
	}
	      // 让当前线程处于阻塞状态,直到锁存器计数为零
          countDownLatch.await();
	}


三、使用注入的方式创建并使用线程池

//启动类
@SpringBootApplication
public class EtlServiceApplication {
 
    public static void main(final String[] args) {
        SpringApplication.run(EtlServiceApplication.class, args);
    }
        
        //启动类中注入线程池服务
    @Bean
    public ExecutorService executorService(){
        ThreadFactory namedThreadFactory = new ThreadFactoryBuilder()
                .setNameFormat("sch-pool-%d").build();
        ExecutorService pool = new ThreadPoolExecutor(20, 500,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<>(4096), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy());
        return pool;
    }
}
 
 
//使用类中注入
@Autowired
private ExecutorService executorService;
 
//实用类中使用
//我们通常使用两种方式来创建线程:集成Thread类和实现Runnable接口
executorService.execute(Runnable runnable);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值