【学习笔记】【线程池】【ThreadPoolExecutor】了解与学习

【参考来源】:
【1】https://www.jianshu.com/p/c41e942bcd64
【2】https://www.jianshu.com/p/f030aa5d7a28
【3】https://www.cnblogs.com/zhaoyan001/p/7049627.html
【4】https://blog.csdn.net/weixin_37910453/article/details/86523454
【5】https://www.iteye.com/blog/zapldy-746458

基础知识

ThreadPoolExecutor的四个构造方法

ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
                                TimeUnit unit, BlockingQueue<Runnable> workQueue)
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime,
                       TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory)
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
                                 BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler)
ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit,
    BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler, ThreadFactory threadFactory)

在这里插入图片描述

接口参数的含义

名称 意思 类型
corePoolSize 核心线程池的大小 int
maximumPoolSize 最大线程池大小 int
keepAliveTime 线程最大空闲时间 long
unit 时间单位 TimeUnit
workQueue 线程等待队列 BlockingQueue < Runnable >
threadFactory 线程创建工厂 ThreadFactory
handler 拒绝策略 RejectedExecutionHandler

线程池实战

【例1】循环100次统计一个数值,每次计算累加的操作耗时 100毫秒。单线程和多线程的做法。

public static void no() throws Exception {
    
    
	long start = System.currentTimeMillis();
	Integer count = 100;
	Integer sum = 0;
	for (int a = 0; a < count; a++) {
    
    
		sum += a;
		Thread.sleep(100);
	}
	System.out.println(String.format("结果:%d\n耗时:%d", sum, System.currentTimeMillis() - start));
}

public static void yes() throws Exception {
    
    
	long start = System.currentTimeMillis();
	Integer count = 100;
	// CountDownLatch 在完成最后一次计算后通知程序已经计算完成,节省等待时间
	// CountDownLatch其实可以把它看作一个计数器,只不过这个计数器的操作是原子操作,
	// 同时只能有一个线程去操作这个计数器,
	// 也就是同时只能有一个线程去减这个计数器里面的值。
	CountDownLatch countDownLatch = new CountDownLatch(count);
	// 使用AtomicInteger,线程是安全的,保证了数据正确性
	AtomicInteger sum = new AtomicInteger(0);
	for (int a = 0; a < count; a++) {
    
    
		final Integer e = a;
		new Thread(() -> {
    
    
		sum.getAndAdd(e);
		try {
    
    
			Thread.sleep(100);
		} catch (InterruptedException e1) {
    
    
			e1.printStackTrace();
		}
		countDownLatch.countDown();
		}).start();
	}
	countDownLatch.await();
	System.out.println(String.format("结果:%d\n耗时:%d", sum.get(), System.currentTimeMillis() - start));
}

public static void main(String[] args) throws Exception {
    
    
	System.out.println("普通做法");
	no();
	System.out.println("多线程做法");
	yes();
}

【运行结果】

在这里插入图片描述

【例2】三个工人为老板干活,当三个工人把一天的活都干完了的时候,老板就来检查所有工人所干的活。

两个实体类,Worker代表工人,Boss代表老板。

CountDownLatch的一个非常典型的应用场景是:有一个任务想要往下执行,但必须要等到其他的任务执行完毕后才可以继续往下执行。假如我们这个想要继续往下执行的任务调用一个CountDownLatch对象的await()方法,其他的任务执行完自己的任务后调用同一个CountDownLatch对象上的countDown()方法,这个调用await()方法的任务将一直阻塞等待,直到这个CountDownLatch对象的计数值减到0为止。
Atomiclong( ) 可以理解是加了synchronized的long。

【Woker类】

// Worker类
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;

public class Worker implements Runnable {
    
    

	private CountDownLatch cdl;
	private String name;

	public Worker(CountDownLatch cdl, String name) {
    
    
		this.cdl = cdl;
		this.name = name;
	}

	public void run() {
    
    
		this.doWork();
		try {
    
    
			TimeUnit.SECONDS.sleep(new Random().nextInt(10));
		} catch (InterruptedException ie) {
    
    
		}
		System.out.println(this.name + "活干完了!");
		this.cdl.countDown();

	}

	private void doWork() {
    
    
		System.out.println(this.name + "正在干活!");
	}

}

【Boss类】

// Boss类
import java.util.concurrent.CountDownLatch;  

public class Boss implements Runnable {
    
      
  
    private CountDownLatch downLatch;  
      
    public Boss(CountDownLatch downLatch){
    
      
        this.downLatch = downLatch;  
    }  
      
    public void run() {
    
      
        System.out.println("老板正在等所有的工人干完活......");  
        try {
    
      
            this.downLatch.await();  
        } catch (InterruptedException e) {
    
      
        }  
        System.out.println("工人活都干完了,老板开始检查了!");  
    }  
  
}  

【主类】

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Demo {
    
    
	public static void main(String[] args) {
    
    
		ExecutorService executor = Executors.newCachedThreadPool();

		CountDownLatch cdl = new CountDownLatch(3);

		Worker w1 = new Worker(cdl, "张三");
		Worker w2 = new Worker(cdl, "李四");
		Worker w3 = new Worker(cdl, "王二");

		Boss boss = new Boss(cdl);

		executor.execute(w3);
		executor.execute(w2);
		executor.execute(w1);
		executor.execute(boss);

		executor.shutdown();
	}
}

【运行结果】

在这里插入图片描述
【知识】:运行主类的时候,可以肯定的每次运行的结果可能与图的不一样,但老板检查永远是在后面的。

猜你喜欢

转载自blog.csdn.net/qq_43263647/article/details/109474272