一、ThreadPoolTaskExecutor
传统的ThreadPoolExecutor,但是spring提供了一个ThreadPoolTaskExecutor,
ThreadPoolTaskExecutor 是 Spring 提供的一个方便的线程池实现,用于异步执行任务或处理并发请求
在使用 ThreadPoolTaskExecutor 作为 Spring Bean 注册到容器中后,Spring 会负责在应用程序关闭时自动关闭所有注册的线程池,所以不需要手动关闭。这样不仅可以确保线程池中的线程正确地停止,还可以防止资源泄露和潜在的并发问题。
- ThreadPoolProperties
@Data
@Configuration
@ConfigurationProperties(prefix = "thread.pool")
public class ThreadPoolProperties {
/**
* 核心线程池大小
*/
private int corePoolSize;
/**
* 最大可创建的线程数
*/
private int maxPoolSize;
/**
* 队列最大长度
*/
private int queueCapacity;
/**
* 线程池维护线程所允许的空闲时间
*/
private int keepAliveSeconds;
}
- ThreadPoolConfig
@Configuration
public class ThreadPoolConfig
{
/*
@Value("${thread.pool.corePoolSize}")
private String corePoolSize;
@Value("${thread.pool.maxPoolSize}")
private String maxPoolSize;
@Value("${thread.pool.queueCapacity}")
private String queueCapacity;
@Value("${thread.pool.keepAliveSeconds}")
private String keepAliveSeconds;
*/
//线程池配置
@Resource
private ThreadPoolProperties threadPoolProperties;
@Bean
public ThreadPoolTaskExecutor threadPoolTaskExecutor()
{
ThreadPoolTaskExecutor threadPool = new ThreadPoolTaskExecutor();
// 核心线程池大小
threadPool.setCorePoolSize(threadPoolProperties.getCorePoolSize());
// 最大可创建的线程数
threadPool.setMaxPoolSize(threadPoolProperties.getMaxPoolSize());
// 等待队列最大长度
threadPool.setQueueCapacity(threadPoolProperties.getQueueCapacity());
// 线程池维护线程所允许的空闲时间
threadPool.setKeepAliveSeconds(threadPoolProperties.getKeepAliveSeconds());
//异步方法内部线程名称
threadPool.setThreadNamePrefix("spring默认线程池-");
// 线程池对拒绝任务(无线程可用)的处理策略
threadPool.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
// 任务都完成再关闭线程池
threadPool.setWaitForTasksToCompleteOnShutdown(true);
// 任务初始化
threadPool.initialize();
return threadPool;
}
}
二、ThreadLocal 、InheritableThreadLocal、TransmittableThreadLocal
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>transmittable-thread-local</artifactId>
<version>2.14.3</version>
</dependency>
线程 ThreadLocal
父子线程共享传递 InheritableThreadLocal
线程池共享传值 TransmittableThreadLocal
https://blog.csdn.net/lucky_love816/article/details/124986962
package com.yubin.face.threadlocal;
import com.alibaba.ttl.TransmittableThreadLocal;
import com.alibaba.ttl.threadpool.TtlExecutors;
import lombok.extern.slf4j.Slf4j;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
* project : face
* <p> </p>
*父子线程共享传递 InheritableThreadLocal
* 线程池共享传值 TransmittableThreadLocal
*
* @author
* @date 2024-11-17【星期日】
**/
@Slf4j
public class ThreadLocalDemo3 {
public static void main(String[] args) {
//m1();
//m2();
//m3(); //InheritableThreadLocal
//m4();
m5(); //TransmittableThreadLocal
}
private static void m5() {
TransmittableThreadLocal<String> transmittableThreadLocal = new TransmittableThreadLocal<>();
//为了看到效果,这里创建大小为1的线程池方便看到效果,池中只有1个线程才有效果,池中只有1个线程才有效果
ExecutorService threadPool = Executors.newSingleThreadExecutor();
//这里需要用 TtlExecutors.getTtlExecutorService 将原线程池包装下
threadPool = TtlExecutors.getTtlExecutorService(threadPool);
//这里是主线程,使用 transmittableThreadLocal.set 放入值:Java
transmittableThreadLocal.set(Thread.currentThread().getName() + "-Java");
log.info("major:{}", transmittableThreadLocal.get());
//在线程池中通过 transmittableThreadLocal 拿值,看看能否拿到 刚才放入的Java?
threadPool.execute(() -> {
log.info("threadPool第1次获取 major:{}", transmittableThreadLocal.get());
});
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println();
System.out.println();
//这里又在主线程中放入了Vue
transmittableThreadLocal.set(Thread.currentThread().getName() + "-Vue我已经修改了,O(∩_∩)O");
log.info("major:{}", transmittableThreadLocal.get());
//这里又在线程池中通过 transmittableThreadLocal.get 方法拿值,看看能否拿到 刚才放入的Vue?
threadPool.execute(() -> {
//在线程池中通过 transmittableThreadLocal 拿值,看看能否拿到?
log.info("threadPool第2次获取 major:{}", transmittableThreadLocal.get());
});
System.out.println();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
threadPool.shutdown();
/**
* 解决线程池中线程因为复用而不能取得外部线程数据的问题
*/
}
private static void m4() {
//InheritableThreadLocal:遇到线程池,会有问题
InheritableThreadLocal<String> inheritableThreadLocal = new InheritableThreadLocal();
//这里是主线程,使用 InheritableThreadLocal.set 放入值:Java
inheritableThreadLocal.set(Thread.currentThread().getName() + "-Java");
log.info("major:{}", inheritableThreadLocal.get());
//为了看到效果,这里创建大小为1的线程池方便看到效果,池中只有1个线程才有效果,池中只有1个线程才有效果
ExecutorService threadPool = Executors.newFixedThreadPool(1);
//在线程池中通过 InheritableThreadLocal 拿值,看看能否拿到 刚才放入的Java?
threadPool.execute(() -> {
log.info("threadPool第1次获取 major:{}", inheritableThreadLocal.get());
});
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println();
System.out.println();
//这里又在主线程中放入了Vue
inheritableThreadLocal.set(Thread.currentThread().getName() + "-Vue我已经修改了,O(∩_∩)O");
log.info("major:{}", inheritableThreadLocal.get());
//这里又在线程池中通过 InheritableThreadLocal.get 方法拿值,看看能否拿到 刚才放入的Vue?
threadPool.execute(() -> {
//在线程池中通过 inheritableThreadLocal 拿值,看看能否拿到?
log.info("threadPool第2次获取 major:{}", inheritableThreadLocal.get());
});
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
threadPool.shutdown();
/**
* new新建可以
* 复用不好使,没有new
*/
}
private static void m3() {
InheritableThreadLocal<String> inheritableThreadLocal = new InheritableThreadLocal();
//这里是主线程,使用 InheritableThreadLocal.set 放入值:Java
inheritableThreadLocal.set(Thread.currentThread().getName() + "-Java");
log.info("major:{}", inheritableThreadLocal.get());
//新建线程thread1,在子线程thread1中去ThreadLocal中拿main线程放入值,能否拿到?
//使用InheritableThreadLocal,子线程可以获得父线程set进去的值
new Thread(() -> {
log.info("major:{}", inheritableThreadLocal.get());
}, "thread1").start();
new Thread(() -> {
log.info("major:{}", inheritableThreadLocal.get());
}, "thread2").start();
new Thread(() -> {
log.info("major:{}", inheritableThreadLocal.get());
}, "thread3").start();
}
private static void m2() {
ThreadLocal<String> threadLocal = ThreadLocal.withInitial(() -> null);
//这里是主线程,ThreadLocal中设置了值:Java
threadLocal.set(Thread.currentThread().getName() + "-Java");
log.info("major:{}", threadLocal.get());
//新建线程thread1,在子线程thread1中去ThreadLocal中拿main线程放入值,能否拿到?
//自己set的才能自己get,别人的取不到,分灶吃饭,自取自划
new Thread(() -> {
log.info("major:{}", threadLocal.get());
}, "thread1").start();
}
private static void m1() {
//ThreadLocal可以在当前线程中共享数据,set/get需要在同一个线程中执行才行,别人的取不到
ThreadLocal<String> threadLocal = ThreadLocal.withInitial(() -> null);
threadLocal.set(Thread.currentThread().getName() + "-Java");
log.info("major:{}", threadLocal.get());
System.out.println();
//新建线程thread1,设置Vue,然后取出学科名看看?
new Thread(() -> {
log.info("major:{}", threadLocal.get());//thread1是否可以取得main线程上一步写入的值?
threadLocal.set(Thread.currentThread().getName() + "-Vue");
log.info("major:{}", threadLocal.get());
}, "thread1").start();
System.out.println();
//暂停几秒钟线程
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
//新建线程thread2,设置Flink,然后取出学科名看看?
new Thread(() -> {
log.info("major:{}", threadLocal.get());
threadLocal.set(Thread.currentThread().getName() + "-Flink");
log.info("major:{}", threadLocal.get());
}, "thread2").start();
System.out.println();
CompletableFuture.supplyAsync(() -> {
log.info("major:{}", threadLocal.get());
threadLocal.set(Thread.currentThread().getName() + "-mysql");
log.info("major:{}", threadLocal.get());
return null;
});
System.out.println();
//暂停毫秒
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
1313

被折叠的 条评论
为什么被折叠?



