线程池使用场景

eg:异步发送邮箱通知

public interface SendEmailService {
    /**
     * 发送邮件
     *
     * @param emailDTO 邮件对象
     */
    void sendEmail(EmailDTO emailDTO);
}

接着是邮件发送的简单实现类:

@Service
public class SendEmailServiceImpl implements SendEmailService {
    @Resource
    private ExecutorService emailTaskPool;
    @Override
    public void sendEmail(EmailDTO emailDTO) {
        emailTaskPool.submit(() -> {
            try {
                System.out.printf("sending email .... emailDto is %s \n", emailDTO);
                Thread.sleep(1000);
                System.out.println("sended success");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
    }
}

邮件的发送逻辑通过一个简单的线程睡眠来模拟发送过程中的耗时操作。

然后是线程池方面的配置:

@Configuration
public class ThreadPoolConfig {
    @Bean
    public ExecutorService emailTaskPool() {
        return new ThreadPoolExecutor(2, 4,
                0L, TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>());
    }
}

 controller模块的触发

@RestController
@RequestMapping(value = "/test")
public class TestController {
    @Resource
    private SendEmailService sendEmailService;
    @GetMapping(value = "/send-email")
    public boolean sendEmail() {
        EmailDTO emailDTO = new EmailDTO();
        emailDTO.setContent("测试文案");
        emailDTO.setReceiver("idea");
        emailDTO.setTitle("邮件标题");
        sendEmailService.sendEmail(emailDTO);
        return true;
    }
}

有返回值的,并且调用线程池的线程去执行业务:

    @Resource
    private ExecutorService emailTaskPool;    

    @Override
    public List<TUser> returnData() {
        //创建线程池
        //ExecutorService pool = Executors.newSingleThreadExecutor();
        //定义Callable
        Callable<List<TUser>> callable = new Callable() {
            @Override
            public Object call() throws Exception {
                List<TUser> tUsers = userMapper.selectList(null);
                return tUsers;
            }
        };
        //返回Future,实际上是FutureTask实例
        Future<List<TUser>> future = emailTaskPool.submit(callable);
        try {
            List<TUser> list = future.get();
            return list;
        } catch (Exception e) {
            e.printStackTrace();
        } 
        return null;
    }

### Java 线程池使用场景 Java线程池广泛应用于各种需要处理并发任务的应用程序中。常见的应用场景包括但不限于: - **Web服务器请求处理**:当Web服务器接收到多个客户端请求时,可以利用线程池来并行处理这些请求,从而提高系统的响应速度和吞吐量[^1]。 - **批处理作业**:对于一些后台运行的任务,比如文件传输、日志记录等操作,可以通过线程池来进行批量处理,在不影响主线程的情况下完成工作[^4]。 - **GUI应用程序事件驱动模型**:图形界面通常采用单一线程负责UI更新,而其他耗时的操作则交给线程池去执行,这样能保持用户交互流畅性。 ### 如何与设计模式搭配 #### 单例模式 (Singleton Pattern) 为了确保整个应用程序只有一个全局共享的线程池实例,可以考虑使用单例模式。这有助于控制资源消耗,并简化配置管理。 ```java public class SingletonThreadPool { private static final ExecutorService instance; static { instance = Executors.newFixedThreadPool(10); } public static ExecutorService getInstance() { return instance; } } ``` #### 生产者消费者模式 (Producer Consumer Pattern) 生产者不断生成新任务放入队列;消费者即工作者线程从队列取出任务加以处理。这种模式非常适合于描述多线程环境下任务分发机制的工作流程。 ```java BlockingQueue<Runnable> queue = new LinkedBlockingDeque<>(); ExecutorService executor = new ThreadPoolExecutor( 2, // 核心线程数 4, // 最大线程数 60L, TimeUnit.SECONDS, queue); // 模拟生产者提交任务到线程池 for (int i=0;i<8;i++){ Runnable task=new Task(); executor.execute(task); } class Task implements Runnable{ @Override public void run(){ System.out.println(Thread.currentThread().getName()+" is running"); } } ``` ### 最佳实践建议 选择合理的`corePoolSize`, `maximumPoolSize` 和 `keepAliveTime` 参数至关重要。过少的核心线程可能导致CPU利用率不足,过多则会增加上下文切换成本。一般而言,可以根据具体硬件条件和服务负载特性调整上述参数设置[^2]。 另外,合理选用阻塞队列类型也十分关键。例如,如果希望严格限制等待中的任务数量,则可以选择有界队列;反之,若更关注高吞吐率而非内存占用情况的话,无界队列可能是更好的选项[^3]。 最后值得注意的是,应当谨慎对待拒绝策略的选择。默认情况下,当线程池无法接纳新的任务时将会抛出异常,但这未必总是最理想的解决方案。开发者可根据实际情况自定义相应的错误恢复措施或限流手段。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Lin_XXiang

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值