记一次并发工具类countdownlantch 在线程池中的使用

首先 新建一个 ThreadFactory:

package cn.likui.common.thread.pool;

import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author lidongge
 * @Description:
 * @date 2018/12/25 上午10:23
 */
public class NamedThreadFactory implements ThreadFactory {
    private static final AtomicInteger poolNumber = new AtomicInteger(1);
    private final ThreadGroup group;
    private final AtomicInteger threadNumber = new AtomicInteger(1);
    private final String namePrefix;

    NamedThreadFactory(String name) {

        SecurityManager s = System.getSecurityManager();
        group = (s != null) ? s.getThreadGroup() : Thread.currentThread().getThreadGroup();
        if (null == name || name.isEmpty()) {
            name = "pool";
        }

        namePrefix = name + "-" + poolNumber.getAndIncrement() + "-thread-";
    }

    @Override
    public Thread newThread(Runnable r) {
        Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
        if (t.isDaemon()) {
            t.setDaemon(false);


        }
        if (t.getPriority() != Thread.NORM_PRIORITY) {

            t.setPriority(Thread.NORM_PRIORITY);

        }
        return t;
    }

}

其次 需要定义一个Configuration   bean   ThreadPoolConfig  :

package cn.likui.common.thread.pool;

import lombok.extern.slf4j.Slf4j;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * @author lidongge
 * @Description: 自定义线程池
 * @date 2018/11/05 上午9:59
 */
@Slf4j
@Configuration
public class ThreadPoolConfig {

    @Bean
    public ExecutorService getThreadPool() {
        ExecutorService es = new ThreadPoolExecutor(3,
                Integer.MAX_VALUE,
                0L,
                TimeUnit.MILLISECONDS,
                new LinkedBlockingQueue<Runnable>(),
                new NamedThreadFactory("zhangpeng_study")) {

            @Override
            public void beforeExecute(Thread t, Runnable r) {
                super.beforeExecute(t, r);
                log.info("===》工作线程:{} ,任务线程:{}准备执行",((Thread) r).getName(),t.getName());
            }

            @Override
            public void afterExecute(Runnable r, Throwable t) {
                super.afterExecute(r, t);
                log.info("===》工作线程{}执行完成", ((Thread) r).getName(),t);
            }

            @Override
            public void terminated() {
                super.terminated();
                log.info("===》线程池退出");
            }

            @Override
            public void execute(Runnable job) {
                super.execute(wrap(job, clientTrace(), Thread.currentThread().getName()));
            }
            //捕获异常
            private Runnable wrap(Runnable job, Exception clientTrace, String name) {
                return new Thread(){
                    @Override
                    public void run(){

                        try {
                            job.run();
                        } catch (Exception e) {
                            log.error("===》线程池中线程执行出现异常:{} ,e:{}", clientTrace,e);
                        }
                    }

                };
            }

            private Exception clientTrace() {
                return new Exception("client statck trace");
            }
        };
        return es;
    }
}

然后编写自己的 县城处理核心代码:

package cn.likui.common.thread.handle;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;

/**
 * @Description:
 * @Author: lidongge
 * @Date: 2019/10/29 10:47
 */
@Slf4j
public class DataHandleService implements Runnable{

    /** 接收实际方法调用送来的参数,多个参数支持 */
    private CountDownLatch count;
    private List<Integer> paramList ;
    public DataHandleService(CountDownLatch count, List paramList){
        this.count = count;
        this.paramList = paramList;
    }

    @SneakyThrows
    @Override
    public void run() {
        int j = 0;
        for (int i =0; i < paramList.size(); i++) {
            j = j + paramList.get(i);
        }
        log.info("本次循环当前线程名称:{},和等于【{}】",Thread.currentThread().getName(),j);
        count.countDown();
        log.info("剩余任务数量:{}", count.getCount());
    }
}

 

 

最后是对该线程池的调用,期间不计算线程执行完后的返回情况

package cn.likui.study.controller;

import cn.likui.common.thread.handle.DataHandleService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * @Description:  Demo
 * @Author: ldg
 * @Date: 2020/10/10
 */
@Slf4j
@RestController
@RequestMapping("/pool")
public class ThreadPoolController {

    /** 最大线程数*/
    private static final int MAX_THREAD_COUNT = 2;

    @Resource
    private ExecutorService ex;

    @RequestMapping("/testThread")
    @ResponseBody
    public Object testRestTemplate() throws InterruptedException {

        //
        List<Integer> paramList = new ArrayList<>();
        for (int i=0; i< 10000; i++) {
            paramList.add(i);
        }

        //等待4个线程
        CountDownLatch count = new CountDownLatch(MAX_THREAD_COUNT);
        //多线程请求执行开始
        long startTime = System.currentTimeMillis();

        for (int i = 0 ; i < MAX_THREAD_COUNT; i++) {
            try {
                //参数一 count,参数二 其他
                List<Integer> subList = new ArrayList<>();
                if (i == 0) {
                    subList = paramList.subList(0,5000);
                } else {
                    subList = paramList.subList(5001,9999);
                }

                ex.execute(new DataHandleService(count,subList));
            } catch (Exception e) {
                log.error("线程执行中出现异常提前结束", e);

                count.countDown();
                log.error("剩余任务数量:{}", count.getCount());
                e.printStackTrace();
            } finally {
//                ex.shutdown();
            }
        }

        //10秒超时 :超时之前 还未走完线程 会直接走主线
        count.await(20, TimeUnit.SECONDS);
//        ex.shutdown();
        long endTime = System.currentTimeMillis();
        log.info("多线程打印 耗时:"+ (endTime - startTime) + " ms");
        return null;
    }

}

 

posted @ 2023-01-02 22:09  理葵  阅读(112)  评论(0编辑  收藏  举报
希望写博是我人生坚持在做的事情之一。