JDK1.8 Thread类源码解读

本文详细介绍了Java中的Thread类,包括其如何通过extends和implement实现,多种构造方法,线程的属性如name、priority和daemon等,以及线程的生命周期状态。文章还探讨了volatile关键字在多线程环境中的作用,并列举了关键方法如start()、run()、interrupt(),强调了线程安全问题和已废弃的方法。

总结与使用

线程状态

1.extends 和 implement

Thread 类实现了Runnable接口

    @Override
    public void run() {
        if (target != null) {  
            target.run();   // target Thread 类的属性, Runnable target;  
        }
    }

2.构造方法

a. Thread()
b. Thread(Runnable target)
c. protected Thread(Runnable target, AccessControlContext acc)

......

public Thread() {init(null, null, "Thread-" + nextThreadNum(), 0);}
public Thread(Runnable target) { init(null, target, "Thread-" + nextThreadNum(), 0); }
public Thread(Runnable target, String name){init(null, target, name, 0);};
public Thread(String name) {init(null, null, name, 0); }
protected Thread(Runnable target, AccessControlContext acc) {init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);}
public Thread(ThreadGroup group, Runnable target) {init(group, target, "Thread-" + nextThreadNum(), 0);}
public Thread(ThreadGroup group, Runnable target, String name) {init(group, target, name, 0);}
public Thread(ThreadGroup group, Runnable target, String name,long stackSize) {init(group, target, name, stackSize);}
public Thread(ThreadGroup group, String name) {init(group, null, name, 0);}

构造方法中,综合起来总共ThreadGroup,ThreadName,Runnable,StatckSize,AccessControlContext,调用初始化方法 【init】 初始化线程的属性。

3.属性

【name】:线程名, volatile ,线程外可见,
【priority】: 优先级
【daemon】 :线程是否守护线程
【contextClassLoader】:线程上下文类加载器
【uncaughtExceptionHandler】:线程异常未捕获,突然中止调用的Handler未设置时为null
【defaultUncaughtExceptionHandler】:线程突然终止,默认的Handler
【tid】:线程id
【inheritedAccessControlContext】:线程上下文系统资源访问决策,checkPermisssion,继承的快照
【target】:线程执行目标
【statckSize】:线程占用栈大小
【threadStatus】:线程状态,初始化为0,表示未启动
【eetop】: 未查询到使用
【single_step】:是否单步执行此线程
【stillborn】:JVM 状态
【group】:线程所属的组
【threadInitNumber】:线程编号,构造方法调用nextThreadNum(),每次创建线程这个值++
【threadLocals】:线程本地变量
【inheritableThreadLocals】:从构造线程继承的线程本地变量
【nativeParkEventPointer】:JVM私用状态,本机线程结束后依然存在
【threadSeqNumber】:线程序列号,用于生成线程id
【blocker】: Interruptible类,这个对象通过可中断的I/O操作阻塞线程,设置线程中断后,调用阻塞程序的interrupt方法。
【blockerLock】:调用阻塞操作时锁对象
【parkBlocker】:通过LockSupport对线程挂起和恢复,parkBlocker专为LockSupport而设计,用来记录线程堵塞对象,设置好parkBlocker值后,线程挂起,线程恢复后,parkBlocker设置为null。
private volatile String name;
private int            priority;
private boolean     daemon = false;
private ClassLoader contextClassLoader;
private volatile UncaughtExceptionHandler uncaughtExceptionHandler;
private static volatile UncaughtExceptionHandler defaultUncaughtExceptionHandler;
private long tid;
private AccessControlContext inheritedAccessControlContext;
private Runnable target;
private long stackSize;
private volatile int threadStatus = 0;
private long           eetop;
private boolean     single_step;
private boolean     stillborn = false;
private ThreadGroup group;
private static int threadInitNumber;
ThreadLocal.ThreadLocalMap threadLocals = null;
ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;
private long nativeParkEventPointer;
private static long threadSeqNumber;
private volatile Interruptible blocker;
private final Object blockerLock = new Object();
volatile Object parkBlocker;

关于volatile,volatile 声明的对象,线程外可见,但是多个线程修改volatile值时,同样会出现问题,volatile确保的是可见性,但是写操作仍然是不安全的。详细可以了解volatile在内存中的处理方式。

4.方法

Native方法

registerNatives() : 静态块调用,确保在【cinit】前加载,让JVM能够发现native function,通过这个方法,能够随意命名C函数。
currentThread():返回当前正在执行的线程对象的引用
yield():通知调度线程,当前线程愿意放弃当前使用的处理器,通常作为测试使用
setPriority0(int newPriority):设置新的优先级
sleep(long millis):线程休眠,线程休眠会将现场从cpu释放,但是线程占有的锁不会释放
stop0(Object o):线程停止
resume0():恢复被挂起的线程
interrupt0():线程中断方法,设置中断标志
isInterrupted(boolean ClearInterrupted):线程是否中断
holdsLock(Object obj): 判断线程在指定对象上,是否持有监视器锁
suspend0: 线程挂起

Java方法

【init】:

参数:

ThreadGroup 线程所属线程组

Runnable 线程运行

name 线程名

stackSize 初生线程栈大小,0表示忽略

AccessControlContext 用于应该在给定上下文中进行检查,实际上需要在不同上下文中进行(Thread就是典型)

inheritThreadLocals:如果为true ,从构造线程 继承 可继承的线程局部变量的初始值

通过init方法初始化的属性:【name】【group】【daemon】【priority】【contextClassLoader】【inheritedAccessControlContext】【inheritableThreadLocals】【stackSize】【id】

private void init(ThreadGroup g, Runnable target, String name,long stackSize) {init(g, target, name, stackSize, null, true);}
private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc,boolean inheritThreadLocals) {
    //线程名不允许为空,未定义名称的构造方法Java会给定一个默认的名称
    if (name == null) {
        throw new NullPointerException("name cannot be null");
    }
    this.name = name;
    Thread parent = currentThread();//当前正在执行的线程,这个线程作为父线程
    SecurityManager security = System.getSecurityManager();//安全管理器
    if (g == null) {//如果线程组参数为空,那么需要获取到先创建的线程的线程组
        if (security != null) {//如果当前应用程序已经开启了安全管理器,那么通过安全管理器获取线程组,可通过配置-Djava.security.manager开启,相关安全管理器知识,有兴趣可以自行查看
            g = security.getThreadGroup();
        }
        if (g == null) {//如果安全管理器未开启,那么就从父线程中获取线程组
            g = parent.getThreadGroup();
        }
    }
    //确定当前线程是否有修改线程组的权限,如果安全管理器开启,会进行检查,如果未开启,那么不会检查
    g.checkAccess();
    //安全管理器开启情况下
    if (security != null) {
        if (isCCLOverridden(getClass())) {//如果子类方法覆盖了,那么需要进行权限检查,如果安全策略不通过权限检查,那么异常抛出AccessControlException。
            security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
        }
    }
    //增加线程组中未启动线程的计数 Group:nUnstartedThreads++;
    g.addUnstarted();
    //设置线程的相关属性
    this.group = g;
    this.daemon = parent.isDaemon();
    this.priority = parent.getPriority();
    //TODO 看方法代码 当security ==null 时, this.contextClassLoader = parent.getContextClassLoader() 与 this.contextClassLoader = parent.contextClassLoader 效果一样?
    if (security == null || isCCLOverridden(parent.getClass()))
        this.contextClassLoader = parent.getContextClassLoader();
    else
        this.contextClassLoader = parent.contextClassLoader;
    //如果没有传入了acc ,那么获取当前上下文的快照
    this.inheritedAccessControlContext = acc != null ? acc : AccessController.getContext();
    //Runnable
    this.target = target;
    //线程组内优先级
    setPriority(priority);
    //如果可以继承构造线程的本地变量值
    if (inheritThreadLocals && parent.inheritableThreadLocals != null)
        this.inheritableThreadLocals = ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
    //线程初始化栈大小,未指定,则设置为0
    this.stackSize = stackSize;

    //设置线程id
    tid = nextThreadID();
}
【start】

开始执行线程,虚拟机会调用该线程的run方法。

public synchronized void start() {
        //线程如果已经启动,那么抛出异常,同一线程不能启动两次
        if (threadStatus != 0)
            throw new IllegalThreadStateException();
        //添加线程到线程组
        group.add(this);

        boolean started = false;
        try {
            //执行native方法
            start0();
            //没有异常,线程执行成功
            started = true;
        } finally {
            try {
                if (!started) {
                    //如果执行失败了,那么去除组内的这个线程
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
               
            }
        }
    }
【run】

执行线程,如果线程是实现Runnable的类,那么不会执行这个run方法。不然就会执行这个方法。

    @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
【exit】

线程实际退出时,清理线程数据,这个方法是由系统来调用

private void exit() {
    if (group != null) {
        //线程组中清理线程
        group.threadTerminated(this);
        //当前线程的线程组引用设置成null
        group = null;
    }
    //当前线程相关的属性设置null
    target = null;
    threadLocals = null;
    inheritableThreadLocals = null;
    inheritedAccessControlContext = null;
    blocker = null;
    uncaughtExceptionHandler = null;
}
【stop】

线程停止方法,@Deprecated,已被弃用

如果线程已经启动,那么将立即终止。 线程停止会解锁所有已经锁定的监视器,这种终止的操作很不安全。

 public final void stop() {
     //安全检查
     SecurityManager security = System.getSecurityManager();
     if (security != null) {
         checkAccess();
         if (this != Thread.currentThread()) {
             security.checkPermission(SecurityConstants.STOP_THREAD_PERMISSION);
         }
     }
     //如果线程状态不是新建,并且线程被挂起,那么将恢复该线程,否则不处理
     if (threadStatus != 0) {
         resume(); 
     }
     //停止线程
     stop0(new ThreadDeath());
 }
【interrupt】

线程中断,

    public void interrupt() {
        if (this != Thread.currentThread())
            checkAccess();

        synchronized (blockerLock) {
            Interruptible b = blocker;
            if (b != null) {
                //设置中断状态
                interrupt0();
                //调用阻断程序中的中断方法
                b.interrupt(this);
                return;
            }
        }
        interrupt0();
    }
【interrupted】

当前线程是否被中断

【isCCLOverridden】

验证,是否满足安全约束,子类不得覆盖安全性敏感的non-final方法

    private static boolean isCCLOverridden(Class<?> cl) {
        if (cl == Thread.class)
            return false;
        //移除子类安全检查结果队列顶部缓存
        processQueue(Caches.subclassAuditsQueue, Caches.subclassAudits);
        //创建一个弱键
        WeakClassKey key = new WeakClassKey(cl, Caches.subclassAuditsQueue);
        缓存中是否有该键对应的对象,如果有,则取出
        Boolean result = Caches.subclassAudits.get(key);
        if (result == null) {
            //安全检查
            result = Boolean.valueOf(auditSubclass(cl));
            //检查结果存入缓存
            Caches.subclassAudits.putIfAbsent(key, result);
        }
        return result.booleanValue();
    }
【processQueue】

如果队列不为空,移除队列头部元素,并将头部元素map中映射也移除

static void processQueue(ReferenceQueue<Class<?>> queue,ConcurrentMap<? extends WeakReference<Class<?>>, ?> map){
    Reference<? extends Class<?>> ref;
    while((ref = queue.poll()) != null) {
        map.remove(ref);
    }
}
【auditSubclass】

子类安全检查方法,通过反射进行检查,线上上下文加载器的方法 getContextClassLoader,setContextClassLoader,确保不被覆盖

private static boolean auditSubclass(final Class<?> subcl) {
        Boolean result = AccessController.doPrivileged(
            new PrivilegedAction<Boolean>() {
                public Boolean run() {
                    //向上查找父类,直到Thread终止
                    for (Class<?> cl = subcl; cl != Thread.class; cl = cl.getSuperclass()) {
                        try {
                            //如果查询到了方法,返回return,未查询到,异常捕获,不做处理
                            cl.getDeclaredMethod("getContextClassLoader", new Class<?>[0]);
                            return Boolean.TRUE;
                        } catch (NoSuchMethodException ex) {}
                        try {
                            Class<?>[] params = {ClassLoader.class};
                            cl.getDeclaredMethod("setContextClassLoader", params);
                            return Boolean.TRUE;
                        } catch (NoSuchMethodException ex) {}
                    }
                    return Boolean.FALSE;
                }
            }
        );
        return result.booleanValue();
    }
【getContextClassLoader】

获取线程上下文ClassLoader

    @CallerSensitive
    public ClassLoader getContextClassLoader() {
        if (contextClassLoader == null)
            return null;
        SecurityManager sm = System.getSecurityManager();
        if (sm != null) {
            //如果调用者的类加载器不为空且调用者的类加载器与给定的class参数的祖先不同,那么检查RuntimePermission("getClassLoader")权限
            ClassLoader.checkClassLoaderPermission(contextClassLoader,Reflection.getCallerClass());
        }
        return contextClassLoader;
    }
【setPriority】

设置优先级,线程组内

    public final void setPriority(int newPriority) {
        ThreadGroup g;
        checkAccess();
        if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
            throw new IllegalArgumentException();
        }
        if((g = getThreadGroup()) != null) {
            if (newPriority > g.getMaxPriority()) {
                newPriority = g.getMaxPriority();
            }
            setPriority0(priority = newPriority);
        }
    }
【destroy】@Deprecated 销毁线程
【suspend】@Deprecated 线程挂起
【resume】@Deprecated 线程恢复被挂起的线程
【activeCount】

当前线程组(包括子组)中活跃的线程数,递归统计

    public static int activeCount() {
        return currentThread().getThreadGroup().activeCount();
    }
【enumerate】

将当前线程组及其子组的线程复制到指定数组中

    public static int enumerate(Thread tarray[]) {
        return currentThread().getThreadGroup().enumerate(tarray);
    }
【join】

主线程等待子线程执行,Object.wait(), 必须等待对该对象notify,notifyAll 或者超过了等待时间才会释放

public final synchronized void join(long millis) throws InterruptedException {
        long base = System.currentTimeMillis();
        long now = 0;
        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }
    
        if (millis == 0) {
                //如果毫秒数等于0,会一直等待,直到线程死亡
            while (isAlive()) {
                wait(0);
            }
        } else {
                //如果毫秒数不等于0,超出毫秒数之后会退出等待
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {break;}
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }
【dumpStack】 将线程堆栈信息打印,仅用于dubgger
【checkAccess】 安全检查

5.内部类

静态内部类

【Caches】 private static class 缓存子类安全审核结果
private static class Caches {
    //子类安全结果审核的缓存
    static final ConcurrentMap<WeakClassKey,Boolean> subclassAudits = new ConcurrentHashMap<>();
    //已审计子类弱引用队列
    static final ReferenceQueue<Class<?>> subclassAuditsQueue = new ReferenceQueue<>();
}
【WeakClassKey】

类对象的弱键类,继承了弱引用类

题外话:Java 引用类型,强引用,软引用,弱引用,虚引用 ,不了解可以查询一下资料。

 static class WeakClassKey extends WeakReference<Class<?>> {
        private final int hash;
        //构造方法 父类构造,创建一个弱引用,并且放入给定的队列当中,然后设置一个hash值,indentityHashCode只有当引用对象相同时hashcode相同
        WeakClassKey(Class<?> cl, ReferenceQueue<Class<?>> refQueue) {
            super(cl, refQueue);
            hash = System.identityHashCode(cl);
        }
        @Override
        public int hashCode() {
            return hash;
        }
        @Override
        public boolean equals(Object obj) {
            if (obj == this)
                return true;
            if (obj instanceof WeakClassKey) {
                Object referent = get();
                return (referent != null) &&
                       (referent == ((WeakClassKey) obj).get());
            } else {
                return false;
            }
        }
    }

6.枚举类

【State】 线程状态类
public enum State {
        //新建状态,调用了init方法,未调用run
        NEW,
        //运行中,正在虚拟机中执行,如果在等待操作系统分配资源,也是运行中的状态
        RUNNABLE,
        //阻塞状态,等待监视器锁定。
        BLOCKED,
        //线程等待  Thread.join()/Object.wait()  未指定超时时间,LockSupport.park()  。等待另一个线程 执行 Object.notify/notifyAll ,LockSupprot.unpark。
        WAITING,
        //限时等待  Thread.join(timeout) /Object.wait(timeout) Thread.sleep(timeout)指定超时时间,LockSupport.parkNanos()/parkUntil()。 Object.notify/notifyAll 或者超时,状态结束。
        TIMED_WAITING,
        //线程终止
        TERMINATED;
    }
<think>嗯,用户之前让我介绍过Java多线程的基础知识,现在他们想深入了解JUC(java.util.concurrent)的源码。这说明用户可能已经掌握了多线程的基本概念和使用方法,现在想更深入理解底层实现,提升自己的技术水平。 首先,我需要确定用户对JUC的了解程度。他们可能已经用过一些工具,比如ReentrantLock或CountDownLatch,但现在想了解这些内部的机制。用户可能是中高级开发者,希望优化代码性能,或者准备面试,需要深入理解并发框架。 接下来,我需要考虑如何组织内容。直接深入源码可能会让用户感到困惑,所以应该先从JUC的整体结构入手,然后分模块解析核心。比如,原子、锁、同步器、并发集合、线程池等,每个部分都需要挑选关键点进行讲解。 用户可能需要知道关键设计模式,比如AQS(AbstractQueuedSynchronizer),因为这是JUC的核心。需要详细解释AQS的工作原理,如CLH队列、状态管理等。此外,CAS操作和volatile关键字也是实现无锁并发的基础,需要结合源码说明它们的作用。 另外,用户可能对常见的实现感兴趣,比如ReentrantLock的公平锁与非公平锁区别,ConcurrentHashMap的分段锁或CAS优化,线程池的任务调度流程等。需要结合代码示例和流程图,帮助用户理解这些复杂机制。 同时,要注意避免过于冗长的代码展示,而是聚焦在关键方法和设计思路上。例如,AQS的acquire和release方法,以及它们如何被ReentrantLock或Semaphore调用。此外,可以比较不同版本的实现变化,比如JDK1.7和1.8中ConcurrentHashMap的改进,让用户了解优化方向。 最后,需要给出学习建议,推荐用户如何逐步深入源码,比如从简单的AtomicInteger开始,再逐步研究AQS和锁的实现。同时,提醒用户注意调试和测试的重要性,通过实际案例加深理解。 总结下来,回答的结构应该是先概述JUC的重要性,再分模块解析核心源码,结合关键设计模式和具体实现,最后给出学习方法和资源推荐。这样既系统又深入,帮助用户由浅入深地掌握JUC源码。</think>好的!`java.util.concurrent`(JUC)是 Java 并发编程的核心工具包,包含大量高性能、线程安全的工具和框架。深入源码理解其设计思想,能帮助你掌握高并发编程的精髓。以下从 **核心模块**、**设计模式**、**关键源码分析** 三个维度进行详细解读。 --- ### **一、JUC 整体架构** JUC 的核心模块包括: 1. **原子**(Atomic):基于 CAS 的无锁并发操作(如 `AtomicInteger`)。 2. **锁与同步器**(Locks):如 `ReentrantLock`、`AQS`(AbstractQueuedSynchronizer)。 3. **并发容器**(Collections):如 `ConcurrentHashMap`、`CopyOnWriteArrayList`。 4. **线程池**(Executors):`ThreadPoolExecutor`、`ForkJoinPool`。 5. **同步工具**(Tools):`CountDownLatch`、`CyclicBarrier`、`Semaphore`。 6. **并发流与 Future**:如 `CompletableFuture`、`ForkJoinTask`。 --- ### **二、核心源码解读** #### **1. AQS(AbstractQueuedSynchronizer)** AQS 是 JUC 锁和同步器的基石(如 `ReentrantLock`、`Semaphore` 均基于它实现)。 ##### **核心设计** - **状态变量(state)**:通过 `volatile int state` 表示资源状态(如锁的持有次数)。 - **CLH 队列**:一个双向链表实现的等待队列,存储竞争资源的线程。 - **模板方法模式**:子只需实现 `tryAcquire`/`tryRelease`,AQS 负责线程排队和唤醒。 ##### **源码关键方法** ```java // 独占模式获取资源(如 ReentrantLock.lock()) public final void acquire(int arg) { if (!tryAcquire(arg) && acquireQueued(addWaiter(Node.EXCLUSIVE), arg)) selfInterrupt(); } // 子需实现 tryAcquire(如判断 state 是否为0) protected boolean tryAcquire(int arg) { throw new UnsupportedOperationException(); } ``` ##### **实现示例:ReentrantLock 的公平锁** ```java // 公平锁的 tryAcquire 实现 protected final boolean tryAcquire(int acquires) { final Thread current = Thread.currentThread(); int c = getState(); if (c == 0) { if (!hasQueuedPredecessors() && // 关键:检查队列是否有等待线程 compareAndSetState(0, acquires)) { // CAS 更新状态 setExclusiveOwnerThread(current); return true; } } // 处理重入逻辑(state 增加) else if (current == getExclusiveOwnerThread()) { int nextc = c + acquires; setState(nextc); return true; } return false; } ``` --- #### **2. 原子(AtomicInteger)** 原子的核心是 **CAS(Compare-And-Swap)** 操作,直接依赖 CPU 指令(如 x86 的 `cmpxchg`)。 ##### **源码关键实现** ```java public class AtomicInteger extends Number implements java.io.Serializable { private volatile int value; // 通过 volatile 保证可见性 public final int getAndIncrement() { return unsafe.getAndAddInt(this, valueOffset, 1); } } // Unsafe 的 CAS 操作(native 方法) public final class Unsafe { public final native boolean compareAndSwapInt( Object o, long offset, int expected, int x); } ``` ##### **CAS 的 ABA 问题** - **问题**:变量从 A 改为 B 又改回 A,CAS 无法感知中间变化。 - **解决方案**:使用 `AtomicStampedReference` 添加版本号。 --- #### **3. ConcurrentHashMap(JDK 1.8)** JDK 1.8 摒弃分段锁,改用 **CAS + synchronized** 实现更细粒度的锁。 ##### **关键设计** - **Node 数组(table)**:每个桶位(bucket)是一个链表或红黑树。 - **并发控制**: - **CAS 初始化数组**:避免多线程重复初始化。 - **synchronized 锁桶头节点**:仅锁定单个桶,减少竞争。 ##### **putVal 方法核心逻辑** ```java final V putVal(K key, V value, boolean onlyIfAbsent) { if (key == null || value == null) throw new NullPointerException(); int hash = spread(key.hashCode()); int binCount = 0; for (Node<K,V>[] tab = table;;) { Node<K,V> f; int n, i, fh; if (tab == null || (n = tab.length) == 0) tab = initTable(); // CAS 初始化数组 else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) { if (casTabAt(tab, i, null, new Node<K,V>(hash, key, value))) break; // CAS 插入新节点 } else if ((fh = f.hash) == MOVED) tab = helpTransfer(tab, f); // 协助扩容 else { synchronized (f) { // 锁住桶头节点 // 插入链表或红黑树 } } } } ``` --- #### **4. ThreadPoolExecutor** 线程池的核心是 **任务队列** 和 **线程调度策略**。 ##### **核心参数** - **corePoolSize**:核心线程数(即使空闲也不销毁)。 - **workQueue**:任务队列(如 `LinkedBlockingQueue`)。 - **RejectedExecutionHandler**:拒绝策略(如丢弃、抛异常)。 ##### **execute 方法逻辑** ```java public void execute(Runnable command) { if (command == null) throw new NullPointerException(); int c = ctl.get(); if (workerCountOf(c) < corePoolSize) { if (addWorker(command, true)) // 创建新线程执行任务 return; c = ctl.get(); } if (isRunning(c) && workQueue.offer(command)) { // 任务入队 // 二次检查线程池状态 } else if (!addWorker(command, false)) // 尝试创建非核心线程 reject(command); // 触发拒绝策略 } ``` --- ### **三、JUC 设计模式与技巧** 1. **CAS 无锁编程** - 通过 `Unsafe` 直接操作内存,避免锁竞争(如原子、ConcurrentHashMap)。 - 适用场景:读多写少,竞争不激烈。 2. **模板方法模式** - AQS 将公共逻辑(如线程排队)抽象到基,子只需实现特定方法(如 `tryAcquire`)。 3. **写时复制(Copy-On-Write)** - `CopyOnWriteArrayList` 在修改时复制整个数组,保证读操作无锁。 4. **分段锁优化** - JDK 1.7 的 `ConcurrentHashMap` 使用分段锁(Segment),减少锁粒度。 --- ### **四、高频源码面试题** 1. **AQS 的 CLH 队列为什么是双向链表?** - 答:为了支持取消操作(如超时或中断),需要快速定位前驱节点。 2. **ConcurrentHashMap 1.7 和 1.8 的区别?** - 1.7:分段锁 + ReentrantLock; - 1.8:CAS + synchronized + 红黑树。 3. **线程池如何回收空闲线程?** - 答:`ThreadPoolExecutor` 通过 `getTask()` 中的 `poll(keepAliveTime)` 实现超时回收。 --- ### **五、学习建议** 1. **调试源码**:通过 IDE 调试 `ReentrantLock.lock()` 的执行流程。 2. **阅读注释**:JUC 源码注释通常包含设计思路和并发规则。 3. **手写简化版**:尝试实现一个简单的 AQS 或线程池。 理解 JUC 源码不仅能提升并发编程能力,还能深入掌握 Java 的高性能设计哲学。建议从 `AtomicInteger` 和 `ReentrantLock` 入手,逐步扩展到复杂如 `ConcurrentHashMap` 和 `ThreadPoolExecutor`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值