初学者的线程池干货






前言

平时工作中接触多线程并不是很多,自己对多线程也是迷茫,所以在网上搜了些,加上自己的一些见解,希望这篇文章和下面的链接可以带你入门线程池。






一、线程池基础

很好的入门文章

AtomicInteger的用法

盘它AtomicInteger

CountDownLatch详解





二、Demo上手





1.实现功能

多线程实现集合中的每一个元素-1





2.代码

2.1新增list

        List<Integer> list=new ArrayList<>();
        for (int i=0;i<502;i++){
            list.add(i);
        }

2.1线程池配置

        int listSize=list.size();
        //一个线程处理多少条数据
        int part=10;

        //10个为一段  有余数的段数+1
        int segmentedNum=listSize%part!=0?listSize/part+1:listSize/part;

        //是否有余数标识
        boolean status=listSize%part==0;
        
        //配置countDownLatch   等待所有线程执行完
        CountDownLatch countDownLatch=new CountDownLatch(segmentedNum);
        int corePoolSize=4;
        int maximumPoolSize=8;
        long keepAliveTime=10;
        TimeUnit unit=TimeUnit.SECONDS;
        //自定义阻塞队列
        BlockingQueue<Runnable> workQueue=new ArrayBlockingQueue<>(10);
        //自定义线程工厂
        MyThreadFactory threadFactory=new MyThreadFactory();
        //自定义拒绝策略
        RejectedExecutionHandler handler=new MyRejectedExecutionHandler();
        ThreadPoolExecutor threadPoolExecutor=new ThreadPoolExecutor(corePoolSize,maximumPoolSize,
                keepAliveTime,unit,workQueue,threadFactory,handler);
        //启动所有核心线程
        threadPoolExecutor.prestartAllCoreThreads();

2.3自定义线程工厂

class MyThreadFactory implements ThreadFactory{

        private final AtomicInteger mThreadNum=new AtomicInteger(1);

        @Override
        public Thread newThread(Runnable r) {
            Thread t=new Thread(r,"my-thread-"+mThreadNum.getAndIncrement());
            System.out.println(t.getName()+" has been created");
            return t;

    }
}

2.4自定义拒绝策略

class MyRejectedExecutionHandler implements RejectedExecutionHandler{
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        System.out.println(Thread.currentThread().getName()+"被拒绝了");
        System.out.println(r.toString() + " rejected");
        System.out.println(executor.getCompletedTaskCount());
        if (!executor.isShutdown()) {

            System.out.println(Thread.currentThread().getName()+"将要执行自己的run方法");
            //当前线程调用自己的run方法而不是开启新的线程
            r.run();

        }
    }
}

2.5自定义线程实现类(业务逻辑 list元素-1)

class MyTask implements Callable<List<Integer>>{
    private List<Integer> inList;

    //这是个线程安全的list
    private List<Integer> outList;

    //计数器  线程执行一次便向下减1
    private  CountDownLatch latch;

    public CountDownLatch getLatch() {
        return latch;
    }

    public void setLatch(CountDownLatch latch) {
        this.latch = latch;
    }

    public List<Integer> getOutList() {
        return outList;
    }

    public void setOutList(List<Integer> outList) {
        this.outList = outList;
    }

    public List<Integer> getInList() {
        return inList;
    }

    public void setInList(List<Integer> inList) {
        this.inList = inList;
    }

    public MyTask(List<Integer> inList, List<Integer> outList) {
        this.inList = inList;
        this.outList = outList;
    }

    public MyTask(List<Integer> inList, List<Integer> outList, CountDownLatch latch) {
        this.inList = inList;
        this.outList = outList;
        this.latch = latch;
    }

    @Override
    public List<Integer> call() throws Exception {

        for (Integer value : inList) {
            //线程安全的list所以不会有插入数量与实际数量不同
            outList.add(value-1);
        }

        //多线程的线程名
        Thread thread=Thread.currentThread();
        System.out.println(thread.getName());
//        Thread.sleep(5000);
        latch.countDown();

        return outList;
    }

2.6实现类业务逻辑

        List<Integer> tmpList=null;
        //线程安全的保存list元素-1的集合
        List<Integer> outList= Collections.synchronizedList(new ArrayList<>());
        List<Future> futures=new ArrayList<>();
        //一个线程取其中的一段处理
        for (int i=0;i<segmentedNum;i++){
            if (status) {
                //没有余数
                tmpList = list.subList(i*part, (i + 1) * part);
            }else {
                //最后一次循环
                if (i==segmentedNum-1){
                tmpList = list.subList(i*part,listSize);
                }else{
                    tmpList = list.subList(i*part, (i + 1) * part);
                }
            }

            MyTask myTask=new MyTask(tmpList,outList,countDownLatch);
            futures.add( threadPoolExecutor.submit(myTask));
        }



        try {
            //等待所有线程执行完成再执行下一段代码⬇⬇⬇⬇⬇⬇
            countDownLatch.await();
        }catch (InterruptedException e){
            e.printStackTrace();
        }


        //继续执行代码⬇⬇⬇⬇⬇⬇
        try {
            Thread.sleep(5000);
        }catch (InterruptedException e){}
        System.out.println("*******************");
        System.out.println(outList.size());
        System.out.println("*******************");
        //数据是混乱的额需要排序下输出
        Set set=new TreeSet(outList);
        for (Object o : set) {
            System.out.println(o.toString());
        }

        //如果不关闭线程池的话程序将会一直不结束  不会出现Process finished with exit code 0
        threadPoolExecutor.shutdown();

2.7整体代码

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

/**
 * Created by lizhiyi on 2021/9/9.
 */
@Service
public class ThreadPoolDemo{

    public static void main(String[] args) {
        ThreadPoolDemo threadPoolDemo=new ThreadPoolDemo();
        threadPoolDemo.batchProcessingList1();
        System.out.println("主程序执行完毕");
    }



    public  List<Integer> batchProcessingList1() {

        List<Integer> list=new ArrayList<>();
        for (int i=0;i<502;i++){
            list.add(i);
        }

        int listSize=list.size();
        int part=10;
        //10个为一段  有余数的段数+1
        int segmentedNum=listSize%part!=0?listSize/part+1:listSize/part;

        //是否有余数标识
        boolean status=listSize%part==0;
        CountDownLatch countDownLatch=new CountDownLatch(segmentedNum);
        int corePoolSize=4;
        int maximumPoolSize=8;
        long keepAliveTime=10;
        TimeUnit unit=TimeUnit.SECONDS;
        BlockingQueue<Runnable> workQueue=new ArrayBlockingQueue<>(10);
        MyThreadFactory threadFactory=new MyThreadFactory();
        RejectedExecutionHandler handler=new MyRejectedExecutionHandler();
        ThreadPoolExecutor threadPoolExecutor=new ThreadPoolExecutor(corePoolSize,maximumPoolSize,
                keepAliveTime,unit,workQueue,threadFactory,handler);
        threadPoolExecutor.prestartAllCoreThreads();

        List<Integer> tmpList=null;
        //线程安全的保存list元素-1的集合
        List<Integer> outList= Collections.synchronizedList(new ArrayList<>());
        List<Future> futures=new ArrayList<>();
        //一个线程取其中的一段处理
        for (int i=0;i<segmentedNum;i++){
            if (status) {
                //没有余数
                tmpList = list.subList(i*part, (i + 1) * part);
            }else {
                //最后一次循环
                if (i==segmentedNum-1){
                tmpList = list.subList(i*part,listSize);
                }else{
                    tmpList = list.subList(i*part, (i + 1) * part);
                }
            }

            MyTask myTask=new MyTask(tmpList,outList,countDownLatch);
            futures.add( threadPoolExecutor.submit(myTask));
        }



        try {
            //等待所有线程执行完成再执行下一段代码⬇⬇⬇⬇⬇⬇
            countDownLatch.await();
        }catch (InterruptedException e){
            e.printStackTrace();
        }


        //继续执行代码⬇⬇⬇⬇⬇⬇
        try {
            Thread.sleep(5000);
        }catch (InterruptedException e){}
        System.out.println("*******************");
        System.out.println(outList.size());
        System.out.println("*******************");
        //数据是混乱的额需要排序下输出
        Set set=new TreeSet(outList);
        for (Object o : set) {
            System.out.println(o.toString());
        }

        //如果不关闭线程池的话程序将会一直不结束  不会出现Process finished with exit code 0
        threadPoolExecutor.shutdown();
        return outList;
    }
}

/**
 * 自定义的线程工厂 用于生产线程
 * */
class MyThreadFactory implements ThreadFactory{

        private final AtomicInteger mThreadNum=new AtomicInteger(1);

        @Override
        public Thread newThread(Runnable r) {
            Thread t=new Thread(r,"my-thread-"+mThreadNum.getAndIncrement());
            System.out.println(t.getName()+" has been created");
            return t;

    }
}

/**
 * 自定义的拒绝策略  用以阻止线程池满了时候的拒绝策略
 *
 * 触发拒绝策略的条件:corePoolSize(核心线程数)、workQueue(阻塞队列)、maximumPoolSize(最大线程数)
 *
 * 借用一句:当提交任务数大于 corePoolSize 的时候,会优先将任务放到 workQueue 阻塞队列中。当阻塞队列饱和后,
 * 会扩充线程池中线程数,直到达到 maximumPoolSize 最大线程数配置。此时,再多余的任务,则会触发线程池的拒绝策略了。
 * 总结起来,也就是一句话,当提交的任务数大于(workQueue.size() + maximumPoolSize ),就会触发线程池的拒绝策略。
 *
 *
 *
 * 误区需注意:最大可提交任务数不是corePoolSize+workQueue+maximumPoolSize   且maximumPoolSize包含了corePoolSize
 * */
class MyRejectedExecutionHandler implements RejectedExecutionHandler{
    @Override
    public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) {
        System.out.println(Thread.currentThread().getName()+"被拒绝了");
        System.out.println(r.toString() + " rejected");
        System.out.println(executor.getCompletedTaskCount());


        //拒绝了怎么办   按照国际惯例  其实想什么都不做要么就抛出异常
        /**
         * AbortPolicy - 丢弃任务,并抛出拒绝执行 RejectedExecutionException 异常信息。线程池默认的拒绝策略。
         * 必须处理好抛出的异常,否则会打断当前的执行流程,影响后续的任务执行。
         *
         * 本例子使用了CallerRunsPolicy策略
         * CallerRunsPolicy - 当触发拒绝策略,只要线程池没有关闭的话,则使用调用线程直接运行任务。
         * */
        if (!executor.isShutdown()) {

            System.out.println(Thread.currentThread().getName()+"将要执行自己的run方法");
            //当前线程调用自己的run方法而不是开启新的线程
            r.run();

        }
    }
}

/**
 * 自定义线程类   为list中每个元素减一
 * */
class MyTask implements Callable<List<Integer>>{
    private List<Integer> inList;

    //这是个线程安全的list
    private List<Integer> outList;

    //计数器  线程执行一次便向下减1
    private  CountDownLatch latch;

    public CountDownLatch getLatch() {
        return latch;
    }

    public void setLatch(CountDownLatch latch) {
        this.latch = latch;
    }

    public List<Integer> getOutList() {
        return outList;
    }

    public void setOutList(List<Integer> outList) {
        this.outList = outList;
    }

    public List<Integer> getInList() {
        return inList;
    }

    public void setInList(List<Integer> inList) {
        this.inList = inList;
    }

    public MyTask(List<Integer> inList, List<Integer> outList) {
        this.inList = inList;
        this.outList = outList;
    }

    public MyTask(List<Integer> inList, List<Integer> outList, CountDownLatch latch) {
        this.inList = inList;
        this.outList = outList;
        this.latch = latch;
    }

    @Override
    public List<Integer> call() throws Exception {

        for (Integer value : inList) {
            //线程安全的list所以不会有插入数量与实际数量不同
            outList.add(value-1);
        }

        //多线程的线程名
        Thread thread=Thread.currentThread();
        System.out.println(thread.getName());
//        Thread.sleep(5000);
        latch.countDown();

        return outList;
    }
}

2.8效果图






总结

线程池基础的链接文章仔细读,写的都很好仔细阅读!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值