多线程设计模式-线程池模式

定义: 使用极其有限的资源(线程池)去处理相对无限的任务

线程池模式UML图

ThreadPool: 负责接收和存储任务以及工作者线程的生命周期管理
    submit: 用于接收一个任务,客户端代码调用该方法向线程池提交一个任务
    shutdown: 关闭线程池对外提供的服务
Promise: 获取相应任务执行结果的凭据对象
    getResult: 获取相应任务的执行结果
    setResult: 设置相应任务的执行结果
WorkQueue: 工作队列,实现任务的缓存
    enqueue: 将任务存入队列
    dequeue: 从队列中取出一个任务
WorkerThread: 负责任务执行的工作者线程
    run: 逐一从工作队列中取出任务执行
    runTask: 执行指定的任务

像发送信息的线程,来一个请求,创建一个线程执行任务,这会造成比较大的开销,涉及到线程的创建和销毁。而Java的线程池的出现大大缓解了线程创建和销毁的开销,可以通过创建线程池ThreadPoolExecutor,让线程池去管理线程的创建和销毁,大大减小开销,也可以降低了系统的负担。下列的代码就是通过ThreadPoolExecutor创建了线程池来管理线程。做一点小小的补充,关于使用ThreadPoolExecutor创建线程池,其实还有其它方式可以创建线程池(如使用Executors去创建),不过业内阿里巴巴公司在内部开发中不允许使用Executors创建线程池,理由如下,主要还是考虑到内存溢出的问题。

package com.bruce.threadPool;

import com.bruce.threadSpecificStorage.ThreadSpecificSecureRandom;
import org.apache.log4j.PropertyConfigurator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.text.DecimalFormat;
import java.util.concurrent.*;

/**
* @Author: Bruce
* @Date: 2019/6/4 13:09
* @Version 1.0
*/
public class SmsVerficationCodeSender {

    private Logger LOG = LoggerFactory.getLogger(SmsVerficationCodeSender.class);

    public static void config() {
        PropertyConfigurator.configure("C:/Users/Bruce/Downloads/LearningJavaProject/practice/designpatternconcurrent/src/main/resource/log4j.properties");
    }

    private static final ExecutorService EXECUTOR =
            new ThreadPoolExecutor(1, Runtime.getRuntime().availableProcessors(), 60, TimeUnit.SECONDS,
                    new SynchronousQueue<Runnable>(), new ThreadFactory() {
                @Override
                public Thread newThread(Runnable r) {
                    Thread t = new Thread(r, "VerfCodeSender");
                    t.setDaemon(true);
                    return t;
                }
            }, new ThreadPoolExecutor.DiscardPolicy());

    public static void main(String[] args) {
        config();

        SmsVerficationCodeSender client = new SmsVerficationCodeSender();

        client.sendVerificationSms("1223049442");
        client.sendVerificationSms("1234442343");
        client.sendVerificationSms("1988323232");

        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void sendVerificationSms(final String msisdn) {
        Runnable task = new Runnable() {
            @Override
            public void run() {
                int verificationCode = ThreadSpecificSecureRandom.INSTANCE.nextInt(99999);
                DecimalFormat df = new DecimalFormat("00000");
                String txtVerCode = df.format(verificationCode);

                sendSms(msisdn, txtVerCode);
            }
        };
        EXECUTOR.submit(task);
    }

    private void sendSms(String msisdn, String verificationCode) {

        LOG.info("Sending verification code " + verificationCode + " to " + msisdn);
    }
}

线程池模式的优点:
1. 抵消线程创建的开销,提高响应性
2. 封装了工作者线程生命周期管理
3. 减少销魂线程的开销

推荐阅读

深入理解Java并发编程(六):使用线程池的正确姿势

参考资料

黄文海 Java多线程编程实战指南(设计模式篇)

黄文海的Github

猜你喜欢

转载自blog.csdn.net/u010145219/article/details/91348664