ThreadLocal和ThreadPoolExecutor

简介: ThreadLocal和ThreadPoolExecutor

公众号merlinsea



ThreadLocal


  • ThreadLocal是每个线程的内部类,内部封装的是一个
  • ThreadLocalMap<Thread,Entry>
  • 可以根据不同的thread获取不同的Entry,即通过ThreadLocalMap将thread和value进行绑定!!
  • 在实际微服务项目开发中我们可以使用ThreadLocal来传递一些参数给后面的方法。
/**
 * ThreadLocalDemo
 */
public class ThreadLocalDemo {
    /**
     * withInitial底层用的是 new SuppliedThreadLocal<>(supplier);
     */
    ThreadLocal<Integer> num = ThreadLocal.withInitial(() -> 0);
    /**
     * 自增并输出num的值
     */
    public void inCreate() {
        Integer myNum = num.get();
        myNum++;
        System.out.println(Thread.currentThread().getName() + "----------->" + myNum);
        num.set(myNum);
    }
    public static void main(String[] args) {
        ThreadLocalDemo threadLocalDemo = new ThreadLocalDemo();
        for (int i = 1; i < 3; i++) {
            int finalI = i;
            new Thread(() -> {
                while (true) {
                    threadLocalDemo.inCreate();
                    try {
                        Thread.sleep(finalI * 1000L);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }
}

640.png


  • ThreadPoolExecutor
  • 为什么会使用线程池:许多后端应用服务会用于处理来自远端大量短小的任务请求,这些请求以某种方式到达后台服务器,可以是以网络协议的方式到达也可以是以消息队列的方式到达,但不管哪种方式,常常出现的情况是单个任务的处理时间短但请求的数量巨大,如果为每一个请求都开辟一个线程处理,那么这种频繁创建和销毁线程的操作是非常损耗系统资源和性能的。
  • 线程池通过集中管理线程的生命周期,这样在一个任务到来的时候就已经有一些空闲的线程等待处理,这样可以把创建线程的开销均摊到多个任务上,同时也防止线程资源被耗尽
/**
 * 线程池Demo
 * 说明线程池的运行机制:
 * 参数说明:
 * 核心线程数10个,一直存在不会被回收
 * 普通线程数最多10个,当普通线程空闲3秒就会被回收,(因为参数给定最多有20个线程,因此普通线程10个)
 * 工作队列可以容纳的任务数是20个
 *
 * 首先线程池中有10个核心线程一直存在,如果来了不超过10个任务,那么核心线程会自动执行这些任务。
 * 在核心线程都在执行任务时后续又来了任务,那么这些来的任务会加入到工作队列中,当核心线程空闲当时候就可以执行工作队列中的任务
 * 在工作队列满了的情况下后续又来了任务,这些来的任务会开启普通线程去执行,最多开10个普通线程
 * 在普通线程都用上的情况下又来了任务,那么会根据线程池配置的拒绝策略处理任务
 */
public class ThreadPoolDemo {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //工作队列
        LinkedBlockingQueue<Runnable> objects = new LinkedBlockingQueue<>(20);
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(10,20,3L,TimeUnit.SECONDS,objects,new CustomPolicy());
        //prestartAllCoreThreads()初始化线程池的核心线程数,否则即使有任务到达,也不会被执行(因为没有核心线程)
        threadPoolExecutor.prestartAllCoreThreads();
        for (int i = 0; i < 50; i++) {
            //向线程池中提交若干任务
            threadPoolExecutor.submit(()->{
                try {
                    Thread.sleep(2000L);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(threadPoolExecutor.getActiveCount());
            });
        }
    }
}


另外,还可以通过Executor框架创建线程池,但建议还是使用ThreadPoolExecutor来创建线程池,因为通过Executor来创建线程池内部还是调用ThreadPoolExecutor来创建,但是Executor框架创建的线程池有发生OOM的风险(主要是因为Executor框架创建的线程池其内部要么核心线程可以开无限多个,要么工作队列无限长,这并不符合线程池管理线程生命周期以达到复用的目的,有报OOM的风险)


leetcode算法教学班双十一优惠详情

奔跑的小梁,公众号:梁霖编程工具库leetcode刷题直播教学,手把手带你刷题,双十一优惠价来啦~~
相关文章
|
5月前
|
监控 Java 调度
Java线程池ThreadPoolExecutor初略探索
Java线程池ThreadPoolExecutor初略探索
|
1月前
|
Java C++
【多线程】JUC的常见类,Callable接口,ReentranLock,Semaphore,CountDownLatch
【多线程】JUC的常见类,Callable接口,ReentranLock,Semaphore,CountDownLatch
33 0
|
2月前
|
并行计算 Java 开发者
JUC工具类: CyclicBarrier详解
`CyclicBarrier`是并发编程领域一个非常实用的同步辅助类,适用于并行任务场景,它提供了一种简便的线程同步机制。正确地理解和使用这个工具,对开发者来说,可以大大简化并行处理逻辑的复杂度,增强代码的健壮性与可维护性。
24 0
|
3月前
|
Java API 调度
JUC线程池: FutureTask详解
总而言之,FutureTask是Java并发编程中一个非常实用的类,它在异步任务执行及结果处理方面提供了优雅的解决方案。在实现细节方面可以搭配线程池的使用,以及与Callable接口的配合使用,来完成高效的并发任务执行和结果处理。
42 0
|
6月前
|
Java
JUC 常用 4 大并发工具类 CountDownLatch、CyclicBarrier、Semaphore、ExChanger
JUC 常用 4 大并发工具类 CountDownLatch、CyclicBarrier、Semaphore、ExChanger
|
Java
Java 利用JUC CountDownLatch 线程池Executors 实现多线程操作
Java 利用JUC CountDownLatch 线程池Executors 实现多线程操作 业务场景:某个业务操作非常耗时,但又必须等这个操作结束后才能进行后续操作
74 0
|
缓存 Java
Java线程池ExecutorService
Java线程池ExecutorService
104 0
浅谈Java线程池中的ThreadPoolExecutor工具类
浅谈Java线程池中的ThreadPoolExecutor工具类
404 0
|
Java 关系型数据库 MySQL
Java并发:ThreadLocal详解
Java并发:ThreadLocal详解
239 1