JUC系列同步工具类之ThreadLocal

Posted 顧棟

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JUC系列同步工具类之ThreadLocal相关的知识,希望对你有一定的参考价值。

ThreadLocal分析

文章目录

ThreadLocal定义

此类提供线程局部变量。这种变量不同于一般变量,因为每个访问该变量(通过ThreadLocal的 get 或 set 方法)的线程都有自己的、独立初始化的变量副本。ThreadLocal实例通常是希望将状态与线程相关联的类中的私有静态字段(例如,用户 ID 或事务 ID)。

只要线程处于活动状态并且ThreadLocal实例可访问,每个线程都持有对其线程局部变量副本的隐式引用; 在线程消失后,它的所有线程本地实例副本都将受到垃圾回收(除非存在对这些副本的其他引用)。

示例

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;

public class ThreadLocalDemo 

    private static final ThreadLocal<String> THREAD_LOCAL_1 = ThreadLocal.withInitial(() -> "0s");
    private static final ThreadLocal<String> THREAD_LOCAL_2 = ThreadLocal.withInitial(() -> "00s");

    private static final CountDownLatch COUNT_DOWN_LATCH = new CountDownLatch(10);

    private static final ThreadPoolExecutor POOL_EXECUTOR = initThreadPool(5, 10, 1000);

    /**
     * 工作线程
     */
    public static class WorkerThreadFactory implements ThreadFactory 
        private final String namePrefix;
        private final AtomicInteger nextId = new AtomicInteger(1);

        WorkerThreadFactory(String whatFeatureOfGroup) 
            this.namePrefix = "From WorkerThreadFactory's " + whatFeatureOfGroup + "-Worker-";
        

        @Override
        public Thread newThread(Runnable task) 
            String name = namePrefix + nextId.getAndIncrement();
            return new Thread(null, task, name, 0);
        
    

    /**
     * 初始化线程池
     */
    public static ThreadPoolExecutor initThreadPool(int corePoolSize, int maxPoolSize, long keepAliveTime) 
        return new ThreadPoolExecutor(
                corePoolSize,
                maxPoolSize,
                keepAliveTime,
                TimeUnit.SECONDS,
                new ArrayBlockingQueue<>(1000),
                new WorkerThreadFactory("ThreadLocalDemo"),
                new ThreadPoolExecutor.AbortPolicy());
    

    public static void main(String[] args) throws InterruptedException 
        for (int i = 0; i < 10; i++) 
            int finalI = i + 1;
            POOL_EXECUTOR.execute(() -> 
                System.out.println("[" + new SimpleDateFormat("HH:mm:ss.SSS").format(new Date())
                        + "]--[" + Thread.currentThread().getName() + "] THREAD_LOCAL_1, threadId:" + Thread.currentThread().getId() + ", " + THREAD_LOCAL_1.get());
                System.out.println("[" + new SimpleDateFormat("HH:mm:ss.SSS").format(new Date())
                        + "]--[" + Thread.currentThread().getName() + "] THREAD_LOCAL_2, threadId:" + Thread.currentThread().getId() + ", " + THREAD_LOCAL_2.get());
                THREAD_LOCAL_1.set("THREAD_LOCAL_1 is " + finalI);
                THREAD_LOCAL_2.set("THREAD_LOCAL_2 is " + finalI);
                System.out.println("[" + new SimpleDateFormat("HH:mm:ss.SSS").format(new Date())
                        + "]--[" + Thread.currentThread().getName() + "] THREAD_LOCAL_1, threadId:" + Thread.currentThread().getId() + ", " + THREAD_LOCAL_1.get());
                System.out.println("[" + new SimpleDateFormat("HH:mm:ss.SSS").format(new Date())
                        + "]--[" + Thread.currentThread().getName() + "] THREAD_LOCAL_2, threadId:" + Thread.currentThread().getId() + ", " + THREAD_LOCAL_2.get());
                THREAD_LOCAL_1.remove();
                THREAD_LOCAL_2.remove();
                COUNT_DOWN_LATCH.countDown();
            );
        
        if (COUNT_DOWN_LATCH.await(2, TimeUnit.MINUTES)) 
            System.out.println("[" + new SimpleDateFormat("HH:mm:ss.SSS").format(new Date()) + "]--[" + Thread.currentThread().getName() + "] is over.");
        

        POOL_EXECUTOR.shutdown();

    

执行结果

[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-3] THREAD_LOCAL_1, threadId:13, 0s
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-4] THREAD_LOCAL_1, threadId:14, 0s
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-1] THREAD_LOCAL_1, threadId:11, 0s
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-3] THREAD_LOCAL_2, threadId:13, 00s
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-1] THREAD_LOCAL_2, threadId:11, 00s
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-3] THREAD_LOCAL_1, threadId:13, THREAD_LOCAL_1 is 3
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-2] THREAD_LOCAL_1, threadId:12, 0s
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-3] THREAD_LOCAL_2, threadId:13, THREAD_LOCAL_2 is 3
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-5] THREAD_LOCAL_1, threadId:15, 0s
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-3] THREAD_LOCAL_1, threadId:13, 0s
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-5] THREAD_LOCAL_2, threadId:15, 00s
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-3] THREAD_LOCAL_2, threadId:13, 00s
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-2] THREAD_LOCAL_2, threadId:12, 00s
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-3] THREAD_LOCAL_1, threadId:13, THREAD_LOCAL_1 is 6
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-1] THREAD_LOCAL_1, threadId:11, THREAD_LOCAL_1 is 1
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-4] THREAD_LOCAL_2, threadId:14, 00s
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-1] THREAD_LOCAL_2, threadId:11, THREAD_LOCAL_2 is 1
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-3] THREAD_LOCAL_2, threadId:13, THREAD_LOCAL_2 is 6
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-4] THREAD_LOCAL_1, threadId:14, THREAD_LOCAL_1 is 4
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-1] THREAD_LOCAL_1, threadId:11, 0s
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-1] THREAD_LOCAL_2, threadId:11, 00s
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-4] THREAD_LOCAL_2, threadId:14, THREAD_LOCAL_2 is 4
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-1] THREAD_LOCAL_1, threadId:11, THREAD_LOCAL_1 is 7
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-4] THREAD_LOCAL_1, threadId:14, 0s
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-1] THREAD_LOCAL_2, threadId:11, THREAD_LOCAL_2 is 7
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-4] THREAD_LOCAL_2, threadId:14, 00s
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-1] THREAD_LOCAL_1, threadId:11, 0s
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-4] THREAD_LOCAL_1, threadId:14, THREAD_LOCAL_1 is 9
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-1] THREAD_LOCAL_2, threadId:11, 00s
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-4] THREAD_LOCAL_2, threadId:14, THREAD_LOCAL_2 is 9
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-1] THREAD_LOCAL_1, threadId:11, THREAD_LOCAL_1 is 10
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-1] THREAD_LOCAL_2, threadId:11, THREAD_LOCAL_2 is 10
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-2] THREAD_LOCAL_1, threadId:12, THREAD_LOCAL_1 is 2
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-2] THREAD_LOCAL_2, threadId:12, THREAD_LOCAL_2 is 2
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-5] THREAD_LOCAL_1, threadId:15, THREAD_LOCAL_1 is 5
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-3] THREAD_LOCAL_1, threadId:13, 0s
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-5] THREAD_LOCAL_2, threadId:15, THREAD_LOCAL_2 is 5
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-3] THREAD_LOCAL_2, threadId:13, 00s
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-3] THREAD_LOCAL_1, threadId:13, THREAD_LOCAL_1 is 8
[17:59:01.646]--[From WorkerThreadFactory's ThreadLocalDemo-Worker-3] THREAD_LOCAL_2, threadId:13, THREAD_LOCAL_2 is 8
[17:59:01.646]--[main] is over.

组成

内部类SuppliedThreadLocal

ThreadLocal 的扩展,从指定的供应商处获取其初始值。

    static final class SuppliedThreadLocal<T> extends ThreadLocal<T> 

        private final Supplier<? extends T> supplier;

        SuppliedThreadLocal(Supplier<? extends以上是关于JUC系列同步工具类之ThreadLocal的主要内容,如果未能解决你的问题,请参考以下文章

JUC系列同步工具类之Phaser

JUC系列LOCK框架系列之七 核心锁类之ReentrantReadWriteLock

JUC系列LOCK框架系列之六 核心锁类之ReentrantLock

java 多线程系列---JUC原子类之AtomicLong原子类

JUC系列LOCK框架系列之四 同步工具类Semaphore

JUC系列LOCK框架系列之三 同步工具类 CountDownLatch