ThreadPoolExecutor单例线程池在业务中的应用

业务中的场景:接口对外开放,对方调接口,推数据过来,前期可能对方接入的业务方比较少,开启的线程也少,所以对我们这边的时间不做要求,所以我们接口是处理了大批数据入库,存云,处理下来整个代码走完要好几分钟,再给对方响应,但是前几天对方突然在微信群里限制了接口的超时时间,超时了之后对方就默认该批数据处理失败,会重新推送这一批数据,导致我们生产库中出现了重复推过来的数据.所以就需要开启另外一条线程执行业务代码,接口的主线程校验完数据之后直接返回响应,以达到超时要求.
可优化的点:这里由于之前同事的代码的线程池都是随用随创建:
ExecutorService executor = Executors.newFixedThreadPool(20);
之后可能会创建多个线程池,所以自己加了个单例的线程池,程序启动则加载,节省了重复创建线程池所消耗的资源,需要线程直接从创建好的线程池取就可以了.

单例的线程池:

/**
 * @author zsc
 * @ClassName GlobalThreadPool
 * @date 2019/11/7 16:07
 */
@Log4j2
public final class GlobalThreadPool {
    /**
     * 核心线程数
     */
    private static final int CORE_POOL_SIZE = 30;
    /**
     * 最大线程数
     */
    private static final int MAXIMUM_POOL_SIZE = 60;
    /**
     * 空闲线程的存活时间
     */
    private static final int KEEP_ALIVE_TIME = 1000;
    /**
     * 任务队列的大小
     */
    private static final int  BLOCKING_QUEUE_SIZE = 1000;

    private GlobalThreadPool() {
    }
    /**
     * 饿汉初始化
     */
    private static final ThreadPoolExecutor EXECUTOR = new ThreadPoolExecutor(
            CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.MILLISECONDS,
            new LinkedBlockingQueue<>(BLOCKING_QUEUE_SIZE),
            new ThreadFactoryBuilder().setNameFormat("global-thread-pool-%d").build(),
            new  ThreadPoolExecutor.CallerRunsPolicy());
    public static ThreadPoolExecutor getExecutor() {
        return EXECUTOR;
    }
}

这里采用的任务拒绝策略为由调用该线程处执行该任务.

调用处的代码:

  param.setStatus("1");
                bwDataExchangeDAO.insertBwData(param);
                //遍历数据,拿到输入流,解析输入流
                log.info("当前线程为:" + Thread.currentThread().getName());
                //开启另一条线程去执行数据解析,以防超时
                GlobalThreadPool.getExecutor().submit(() ->
                        resolveData(param));
            } else {
                bwDataExchangeDAO.insertBwData(param);
            }

主线程调用线程池开启完线程之后就直接把任务扔给这个线程去处理,直接rtn就完事了.
下面看测试代码:

@Test
    public void test11(){
        CountDownLatch countDownLatch = new CountDownLatch(5);
        for (int i = 0; i < 5; i++) {
            GlobalThreadPool.getExecutor().submit(new Runnable() {
                @Override
                public void run() {
                    System.out.println("当前线程为:" + Thread.currentThread().getName());
                    try {
                        Thread.sleep(10000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }finally {
                        //计数减一
                        countDownLatch.countDown();
                    }
                }
            });
        }
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("5个线程已执行完毕");
    }

控制台的输出:

当前线程为:global-thread-pool-0
当前线程为:global-thread-pool-1
当前线程为:global-thread-pool-2
当前线程为:global-thread-pool-3
当前线程为:global-thread-pool-4

5个线程已执行完毕
Java模式是一种常见的设计模式,它可以确保一个类只有一个实,并且提供了一个全局访问点。模式的主要作用是节省公共资源,方便控制,避免多个实造成的问题。以下是Java模式的一些使用场景: 1. 数据库连接池:在一个应用程序中,通常需要连接到数据库来执行各种操作。如果每次需要连接时都创建一个新的连接,那么会浪费大量的资源。使用模式可以确保只有一个数据库连接池实,并且可以在需要时重复使用该实。 2. 配置文件管理器:在一个应用程序中,通常需要读取各种配置文件来配置应用程序的行为。使用模式可以确保只有一个配置文件管理器实,并且可以在需要时重复使用该实。 3. 日志记录器:在一个应用程序中,通常需要记录各种日志信息来帮助调试和排除故障。使用模式可以确保只有一个日志记录器实,并且可以在需要时重复使用该实。 4. 线程池:在一个应用程序中,通常需要执行各种任务,这些任务可以并行执行。使用模式可以确保只有一个线程池,并且可以在需要时重复使用该实。 5. 缓存管理器:在一个应用程序中,通常需要缓存各种数据来提高性能。使用模式可以确保只有一个缓存管理器实,并且可以在需要时重复使用该实。 以下是一个基本的Java模式的代码示: ```java public class Singleton { private static Singleton instance = null; private Singleton() { // 私有构造函数 } public static synchronized Singleton getInstance() { if (instance == null) { instance = new Singleton(); } return instance; } public void doSomething() { // ... } } ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值