SpringBoot系统列 3 - 多线程数据处理(ThreadPoolTaskExecutor、DruidDataSource)

在上篇文章的基础上进行改造:

package com.hello.util;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;

/**
 * 线程工具类
 * @author XIHONGLEI
 * @date 2018-11-13
 */
@Component
public class ThreadPoolUtil {
    private static final Logger LOG = LoggerFactory.getLogger(ThreadPoolUtil.class);

    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    public void executeTask(Runnable task){
        threadPoolTaskExecutor.submit(task);
        //try {
            //注意task.get()会阻塞,直到返回数据为止,所以一般这样用法很少用
            //resp = task.get();
        //} catch (InterruptedException e) {
            //e.printStackTrace();
        //} catch (ExecutionException e) {
            //e.printStackTrace();
        //}
    }
}
package com.hello;

import com.hello.filter.ApiInterceptor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.SpringBootConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;

/**
 * 配置类
 * @author XIHONGLEI
 * @date 2018-10-31
 */
@SpringBootConfiguration
public class WebConfig extends WebMvcConfigurationSupport {

    @Value("${server.port}")
    public String port;

    @Value("${threadpool.core-pool-size}")
    private int corePoolSize;

    @Value("${threadpool.max-pool-size}")
    private int maxPoolSize;

    @Value("${threadpool.queue-capacity}")
    private int queueCapacity;

    @Value("${threadpool.keep-alive-seconds}")
    private int keepAliveSeconds;

    @Override
    protected void addInterceptors(InterceptorRegistry registry) {
        super.addInterceptors(registry);
        // 将 ApiInterceptor 拦截器类添加进去
        registry.addInterceptor(new ApiInterceptor());
    }

    @Bean(name="threadPoolTaskExecutor")
    public ThreadPoolTaskExecutor threadPoolTaskExecutor(){
        ThreadPoolTaskExecutor pool = new ThreadPoolTaskExecutor();
        pool.setKeepAliveSeconds(keepAliveSeconds);
        // 核心线程池数
        pool.setCorePoolSize(corePoolSize);
        // 最大线程
        pool.setMaxPoolSize(maxPoolSize);
        // 队列容量
        pool.setQueueCapacity(queueCapacity);
        // 队列满,线程被拒绝执行策略
        pool.setRejectedExecutionHandler(new java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy());
        return pool;
    }
}
package com.hello.service.impl;

import com.alibaba.druid.pool.DruidDataSource;
import com.alibaba.fastjson.JSONArray;
import com.hello.entity.ContractDetailDto;
import com.hello.service.CheckPositionService;
import com.hello.util.ThreadPoolUtil;
import org.apache.ibatis.mapping.Environment;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
import org.apache.ibatis.transaction.TransactionFactory;
import org.apache.ibatis.transaction.jdbc.JdbcTransactionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;

@Service("checkPositionService")
public class CheckPositonServiceImpl implements CheckPositionService {

    @Autowired
    private ThreadPoolUtil threadPoolUtil;

    private static DruidDataSource dataSourceMDB = null;
    private static SqlSessionFactory sqlSessionFactory = null;
    //声明Connection对象
    Connection con;
    //驱动程序名
    String driver = "com.mysql.jdbc.Driver";
    //URL指向要访问的数据库名mydata
    String url = "jdbc:mysql://localhost:3306/db_hello?useUnicode=true&characterEncoding=utf8&connectTimeout=5000&socketTimeout=60000&autoReconnect=true&failOverReadOnly=false&allowMultiQueries=true";
    //MySQL配置时的用户名
    String user = "root";
    //MySQL配置时的密码
    String password = "root";

    private SqlSession getSqlSession() throws Exception {
        try{
            if(dataSourceMDB == null || sqlSessionFactory == null){
                dataSourceMDB = new DruidDataSource();
                //设置连接参数
                dataSourceMDB.setUrl(url);
                dataSourceMDB.setDriverClassName(driver);
                dataSourceMDB.setUsername(user);
                dataSourceMDB.setPassword(password);
                //配置初始化大小、最小、最大
                dataSourceMDB.setInitialSize(10);
                dataSourceMDB.setMinIdle(10);
                dataSourceMDB.setMaxActive(5000);
                //连接泄漏监测
                //dataSourceMDB.setRemoveAbandoned(true);
                //dataSourceMDB.setRemoveAbandonedTimeout(30);
                //配置获取连接等待超时的时间
                dataSourceMDB.setMaxWait(500000);
                //配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒
                dataSourceMDB.setTimeBetweenEvictionRunsMillis(20000);
                //防止过期
                dataSourceMDB.setValidationQuery("SELECT 'x'");
                dataSourceMDB.setTestWhileIdle(true);
                dataSourceMDB.setTestOnBorrow(true);

                TransactionFactory transactionFactory = new JdbcTransactionFactory();
                Environment environment =  new Environment("development", transactionFactory, dataSourceMDB);
                Configuration configuration = new Configuration(environment);
                sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
                return sqlSessionFactory.openSession();
            }else{
                return sqlSessionFactory.openSession();
            }
        }catch(Exception e){
            throw e;
        }
    }
    private List getContractDetailList(Long contId){
        try{
            List list = new ArrayList<>();
            SqlSession session = getSqlSession();
            con = session.getConnection();
            if(!con.isClosed()){
                System.out.println("Succeeded connecting to the Database!");
            }

            String sql = "SELECT cont_detail_id,detail_start_time,detail_end_time FROM ad_contract_detail WHERE is_del=0 AND cont_id=?";
            PreparedStatement ps = con.prepareStatement(sql);
            ps.setLong(1,contId);
            ResultSet rs = ps.executeQuery();
            while(rs.next()){
                ContractDetailDto dto = new ContractDetailDto();
                dto.setContDetailId(rs.getLong("cont_detail_id"));
                dto.setDetailStartTime(rs.getDate("detail_start_time"));
                dto.setDetailEndTime(rs.getDate("detail_end_time"));
                list.add(dto);
            }
            rs.close();
            con.close();
            session.close();
            return list;
        } catch(Exception e) {
            //数据库驱动类异常处理
            System.out.println("Sorry,can`t find the Driver!");
            e.printStackTrace();
        }
        return null;
    }

    private List checkIsLock(Long contId,List dtoList,String threadName){
        try{
            SqlSession session = getSqlSession();
            con = session.getConnection();
            if(!con.isClosed()){
                System.out.println("Succeeded connecting to the Database!");
            }
            List checkOutList = new ArrayList<>();
            String sql = "SELECT ac.cont_name,ac.cont_id,ac.cont_code,acd.cont_detail_id,acdp.position_id,rp.position_name,rp.position_code " +
                    "FROM rs_position rp " +
                    "INNER JOIN ad_contract_detail_point acdp ON rp.id = acdp.position_id " +
                    "INNER JOIN ad_contract_detail acd ON acdp.cont_detail_id = acd.cont_detail_id " +
                    "INNER JOIN rs_put_plan rpp ON acd.cont_detail_id = rpp.contract_detail_id " +
                    "INNER JOIN ad_contract ac ON ac.cont_id = rpp.contract_id " +
                    "WHERE rpp.point_stauts != 1 AND acd.is_del = 0 AND ac.is_del=0 " +
                    "AND rpp.contract_id NOT IN (?) " +
                    "AND ( " +
                    "        (acd.detail_start_time >= ? AND acd.detail_start_time <= ?) " +
                    "        OR (acd.detail_start_time <= ? AND acd.detail_end_time >= ?) " +
                    "        OR (acd.detail_end_time >= ? AND acd.detail_end_time <= ?) " +
                    ") " +
                    "AND rp.id IN ( " +
                    " SELECT position_id FROM ad_contract_detail_point WHERE cont_detail_id = ? " +
                    ")";
            int i = 1;
            for(ContractDetailDto dto : dtoList){
                System.out.println("[".concat(threadName).concat("]正在执行第:").concat(i+"").concat("条"));
                PreparedStatement ps = con.prepareStatement(sql);
                ps.setLong(1,contId);
                java.sql.Date sTime = new java.sql.Date(dto.getDetailStartTime().getTime());
                java.sql.Date eTime = new java.sql.Date(dto.getDetailEndTime().getTime());
                ps.setDate(2,sTime);
                ps.setDate(3,eTime);
                ps.setDate(4,sTime);
                ps.setDate(5,eTime);
                ps.setDate(6,sTime);
                ps.setDate(7,eTime);
                ps.setLong(8,dto.getContDetailId());
                ResultSet rs = ps.executeQuery();
                while(rs.next()){
                    ContractDetailDto cdDto = new ContractDetailDto();
                    cdDto.setContDetailId(rs.getLong("cont_detail_id"));
                    cdDto.setPositionId(rs.getLong("position_id"));
                    cdDto.setPositionCode(rs.getString("position_code"));
                    cdDto.setPositionName(rs.getString("position_name"));
                    cdDto.setContId(rs.getLong("cont_id"));
                    cdDto.setContName(rs.getString("cont_name"));
                    cdDto.setContCode(rs.getString("cont_code"));
                    checkOutList.add(cdDto);
                }
                i+=1;
                rs.getStatement().close();
                rs.close();
                ps.close();
            }
            con.close();
            session.close();
            return checkOutList;
        } catch(Exception e) {
            //数据库驱动类异常处理
            System.out.println("Sorry,can`t find the Driver!");
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public void checkPosition(Long contId) {
        List detailDtoList = this.getContractDetailList(contId);
        if(detailDtoList != null && detailDtoList.size() > 0){
            List threadList1 = new ArrayList<>();
            List threadList2 = new ArrayList<>();
            List threadList3 = new ArrayList<>();
            if(detailDtoList.size() <= 3){
                threadList1.addAll(detailDtoList);
            }else{
                int stepLen = detailDtoList.size() / 3;
                int i = 1;
                for(ContractDetailDto dto : detailDtoList){
                    if(i <= stepLen){
                        threadList1.add(dto);
                    }else if(i> stepLen && i <= stepLen * 2){
                        threadList2.add(dto);
                    }else{
                        threadList3.add(dto);
                    }
                    i += 1;
                }
            }
            if(threadList1.size() > 0){
                Runnable runnable = () ->{
                    List checkOutList = this.checkIsLock(contId,threadList1,"线程1");
                    try {
                        System.out.println("[线程1]最后结果是:");
                        JSONArray array = new JSONArray();
                        for(ContractDetailDto dto : checkOutList){
                            if(dto.getPositionId() != null && dto.getPositionId() != 0) {
                                array.add(dto.toJsonString());
                            }
                        }
                        System.out.println(array);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                };
                threadPoolUtil.executeTask(runnable);
            }
            if(threadList2.size() > 0){
                Runnable runnable = () ->{
                    List checkOutList = this.checkIsLock(contId,threadList2,"线程2");
                    try {
                        System.out.println("[线程2]最后结果是:");
                        JSONArray array = new JSONArray();
                        for(ContractDetailDto dto : checkOutList){
                            if(dto.getPositionId() != null && dto.getPositionId() != 0) {
                                array.add(dto.toJsonString());
                            }
                        }
                        System.out.println(array);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                };
                threadPoolUtil.executeTask(runnable);
            }
            if(threadList3.size() > 0){
                Runnable runnable = () ->{
                    List checkOutList = this.checkIsLock(contId,threadList2,"线程3");
                    try {
                        System.out.println("[线程3]最后结果是:");
                        JSONArray array = new JSONArray();
                        for(ContractDetailDto dto : checkOutList){
                            if(dto.getPositionId() != null && dto.getPositionId() != 0) {
                                array.add(dto.toJsonString());
                            }
                        }
                        System.out.println(array);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                };
                threadPoolUtil.executeTask(runnable);
            }
        }
    }
}

 

你可能感兴趣的:(SpringBoot系统列 3 - 多线程数据处理(ThreadPoolTaskExecutor、DruidDataSource))