目录
前言
平时工作中接触多线程并不是很多,自己对多线程也是迷茫,所以在网上搜了些,加上自己的一些见解,希望这篇文章和下面的链接可以带你入门线程池。
一、线程池基础
二、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效果图
总结
线程池基础的链接文章仔细读,写的都很好仔细阅读!!!