23.jdk源码阅读之Thread(下)

1. 写在前面

上篇文章我们介绍了Tread的一些方法的底层代码实现,这篇文章我们继续。

2. join()方法的底层实现

在这里插入图片描述

/**
     * Waits at most {@code millis} milliseconds for this thread to
     * die. A timeout of {@code 0} means to wait forever.
     *
     * <p> This implementation uses a loop of {@code this.wait} calls
     * conditioned on {@code this.isAlive}. As a thread terminates the
     * {@code this.notifyAll} method is invoked. It is recommended that
     * applications not use {@code wait}, {@code notify}, or
     * {@code notifyAll} on {@code Thread} instances.
     *
     * @param  millis
     *         the time to wait in milliseconds
     *
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
    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) {
            while (isAlive()) {
                wait(0);
            }
        } else {
            while (isAlive()) {
                long delay = millis - now;
                if (delay <= 0) {
                    break;
                }
                wait(delay);
                now = System.currentTimeMillis() - base;
            }
        }
    }

    /**
     * Waits at most {@code millis} milliseconds plus
     * {@code nanos} nanoseconds for this thread to die.
     *
     * <p> This implementation uses a loop of {@code this.wait} calls
     * conditioned on {@code this.isAlive}. As a thread terminates the
     * {@code this.notifyAll} method is invoked. It is recommended that
     * applications not use {@code wait}, {@code notify}, or
     * {@code notifyAll} on {@code Thread} instances.
     *
     * @param  millis
     *         the time to wait in milliseconds
     *
     * @param  nanos
     *         {@code 0-999999} additional nanoseconds to wait
     *
     * @throws  IllegalArgumentException
     *          if the value of {@code millis} is negative, or the value
     *          of {@code nanos} is not in the range {@code 0-999999}
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
    public final synchronized void join(long millis, int nanos)
    throws InterruptedException {

        if (millis < 0) {
            throw new IllegalArgumentException("timeout value is negative");
        }

        if (nanos < 0 || nanos > 999999) {
            throw new IllegalArgumentException(
                                "nanosecond timeout value out of range");
        }

        if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
            millis++;
        }

        join(millis);
    }

    /**
     * Waits for this thread to die.
     *
     * <p> An invocation of this method behaves in exactly the same
     * way as the invocation
     *
     * <blockquote>
     * {@linkplain #join(long) join}{@code (0)}
     * </blockquote>
     *
     * @throws  InterruptedException
     *          if any thread has interrupted the current thread. The
     *          <i>interrupted status</i> of the current thread is
     *          cleared when this exception is thrown.
     */
    public final void join() throws InterruptedException {
        join(0);
    }

这段代码展示了 Java Thread 类中的 join() 方法的几种重载实现。join() 方法的主要功能是让当前线程等待另一个线程的终止。通过调用 join(),当前线程会被阻塞,直到目标线程完成执行。

2.1 join(long millis)

2.1.1 参数

  • millis:等待的时间,以毫秒为单位。值为0表示无限等待。

2.1.2 异常

  • IllegalArgumentException:如果 millis 为负数。
  • InterruptedException:如果当前线程在等待过程中被中断。

2.1.3 实现

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) {
        while (isAlive()) {
            wait(0);
        }
    } else {
        while (isAlive()) {
            long delay = millis - now;
            if (delay <= 0) {
                break;
            }
            wait(delay);
            now = System.currentTimeMillis() - base;
        }
    }
}
  • 记录当前时间。
  • 检查 millis 是否为负数,如果是,则抛出 IllegalArgumentException。
  • 如果 millis 为 0,当前线程会无限期等待,直到目标线程终止。
  • 否则,当前线程会等待指定的毫秒数,使用 wait() 方法进行等待,并定期检查目标线程是否仍然存活。

2.2 join(long millis, int nanos)

2.2.1 参数

  • millis:等待的时间,以毫秒为单位。
  • nanos:额外等待的时间,以纳秒为单位,范围是 0 到 999999。

2.2.2 异常

  • IllegalArgumentException:如果 millis 为负数,或 nanos 不在 0 到 999999 之间。
  • InterruptedException:如果当前线程在等待过程中被中断。

2.2.3 实现

public final synchronized void join(long millis, int nanos) throws InterruptedException {
    if (millis < 0) {
        throw new IllegalArgumentException("timeout value is negative");
    }

    if (nanos < 0 || nanos > 999999) {
        throw new IllegalArgumentException("nanosecond timeout value out of range");
    }

    if (nanos >= 500000 || (nanos != 0 && millis == 0)) {
        millis++;
    }

    join(millis);
}

  • 检查 millis 和 nanos 的有效性
  • 如果 nanos 大于等于 500000 或者 nanos 不为 0 且 millis 为 0,则将 millis 增加 1。
  • 调用 join(millis) 方法进行等待。

2.3 join()

调用 join(0) 方法,即无限期等待目标线程终止。

3. interrupt()方法的底层实现

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

        synchronized (blockerLock) {
            Interruptible b = blocker;
            if (b != null) {
                interrupt0();           // Just to set the interrupt flag
                b.interrupt(this);
                return;
            }
        }
        interrupt0();
    }

interrupt() 方法用于中断线程的执行。中断线程的主要目的是通知线程它应该停止当前的工作,并尽快终止。

3.1 中断线程

如果当前线程不是在中断自己(即 this != Thread.currentThread()),则调用 checkAccess() 方法检查权限,可能会抛出 SecurityException。

3.2 线程阻塞的情况

  • 如果线程在调用 Object 类的 wait()、wait(long)、wait(long, int) 方法,或者 Thread 类的 join()、join(long)、join(long, int)、sleep(long)、sleep(long, int) 方法时被阻塞,中断会清除线程的中断状态并抛出 InterruptedException。
  • 如果线程在 I/O 操作中被阻塞(例如在 InterruptibleChannel 上),中断会关闭通道,设置线程的中断状态,并抛出 ClosedByInterruptException。
  • 如果线程在 Selector 上被阻塞,中断会设置线程的中断状态,并立即从选择操作返回,可能返回一个非零值,就像调用了 Selector 的 wakeup 方法一样。
  • 如果以上情况都不适用,则仅设置线程的中断状态。

3.3 中断非活动线程

中断一个不活跃的线程可能没有任何效果。

3.4 同步块

synchronized (blockerLock) {
        Interruptible b = blocker;
        if (b != null) {
            interrupt0();           // Just to set the interrupt flag
            b.interrupt(this);
            return;
        }
    }
  • 使用 blockerLock 对象进行同步,以确保在检查和修改 blocker 时的线程安全。
  • Interruptible b = blocker;:获取当前线程的 blocker 对象。
  • 如果 blocker 不为 null,调用 interrupt0() 方法设置中断标志,然后调用 blocker 的 interrupt(this) 方法进行中断处理,并返回。

3.5 设置中断标志

如果 blocker 为 null,直接调用 interrupt0() 方法设置中断标志。

3.6 interrupt0()

本地方法,用于设置线程的中断状态。

4. setPriority(int newPriority)

setPriority 方法用于设置线程的优先级。线程的优先级是一个整数值,通常用于调度线程的执行顺序,但具体的调度行为依赖于底层操作系统和 JVM 实现。

4.1 声明变量

ThreadGroup g;

4.2 检查访问权限

checkAccess();

调用 checkAccess() 方法,确保当前线程有权限修改目标线程。如果没有权限,可能会抛出 SecurityException。

4.3 验证优先级范围

if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {
    throw new IllegalArgumentException();
}

检查 newPriority 是否在合法范围内(即不大于 MAX_PRIORITY 且不小于 MIN_PRIORITY)。如果不在范围内,则抛出 IllegalArgumentException。

4.4 获取线程组

if((g = getThreadGroup()) != null) {

获取当前线程所属的线程组 ThreadGroup。如果线程组不为 null,则继续执行。

4.5 调整优先级

if (newPriority > g.getMaxPriority()) {
    newPriority = g.getMaxPriority();
}

如果 newPriority 大于线程组的最大优先级 g.getMaxPriority(),则将 newPriority 调整为线程组的最大优先级。

4.6 设置优先级

setPriority0(priority = newPriority);

调用本地方法 setPriority0(int newPriority) 设置线程的优先级,并将 priority 字段更新为 newPriority。

系列文章

1.JDK源码阅读之环境搭建

2.JDK源码阅读之目录介绍

3.jdk源码阅读之ArrayList(上)

4.jdk源码阅读之ArrayList(下)

5.jdk源码阅读之HashMap

6.jdk源码阅读之HashMap(下)

7.jdk源码阅读之ConcurrentHashMap(上)

8.jdk源码阅读之ConcurrentHashMap(下)

9.jdk源码阅读之ThreadLocal

10.jdk源码阅读之ReentrantLock

11.jdk源码阅读之CountDownLatch

12.jdk源码阅读之CyclicBarrier

13.jdk源码阅读之Semaphore

14.jdk源码阅读之线程池(上)

15.jdk源码阅读之线程池(下)

16.jdk源码阅读之ArrayBlockingQueue

17.jdk源码阅读之LinkedBlockingQueue

18.jdk源码阅读之CopyOnWriteArrayList

19.jdk源码阅读之FutureTask

20.jdk源码阅读之CompletableFuture

21.jdk源码阅读之AtomicLong

22.jdk源码阅读之Thread(上)

  • 13
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

至真源

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值