Thread类黑魔法原理

7 篇文章 0 订阅

Thread类是Java中线程的抽象,是OS线程的一对一映射。

Thread本身提供一些基础的并发控制API,利用它可以做基本的线程交互通信。

将学习到 wait() notify() join() sleep() interrupt() 方法的原理

Java中线程状态流转图

可以看到Java的线程状态对比OS实际上是少了一个running的。JVM把running和ready状态合并成了runnable状态。可能由于Java属于上层应用通常不需要关注到线程当前的调度细分状态,设计者把运行中的状态给屏蔽了。

wait()

线程的wait()是继承自Object.wait()。必须先获取到Object监视器的锁才能在临界区内调用监视器的wait,进入等待状态 WAITTING。

并且线程在临界区进入 WAITTING 状态后,会释放监视器的锁。在后续被其它线程通过notify()唤醒后,需要先获取到锁才从WAITTING转回RUNNABLE。

JVM中处理调用wait方法的线程是,当前线程封装成节点放入监视器对象的等待池,等待未来被某一个线程唤醒。

Object.wait 是native方法。可以配合notify()实现生产者消费者模式。

不过有意思的是有时候会看到源码总是在循环中检查wait状态,是因为存在"假唤醒"的现象。摘抄JDK源码,假唤醒很少出现,但是为了安全还是要在唤醒时循环检查当前是否满足唤醒条件。

A thread can also wake up without being notified, interrupted, or timing out, a so-called spurious wakeup. While this will rarely occur in practice, applications must guard against it by testing for the condition that should have caused the thread to be awakened, and continuing to wait if the condition is not satisfied. In other words, waits should always occur in loops, like this one:

           synchronized (obj) {

               while (<condition does not hold>)

                   obj.wait(timeout);

               ... // Perform action appropriate to condition

           }

      

(For more information on this topic, see Section 3.2.3 in Doug Lea's "Concurrent Programming in Java (Second Edition)" (Addison-Wesley, 2000), or Item 50 in Joshua Bloch's "Effective Java Programming Language Guide" (Addison-Wesley, 2001).

notify()

同样是继承自Object.notify()。直接摘抄JDK中关于此方法的描述。简要概括:

需要获取到锁才能调用此方法。此方法唤醒在监视器中的一个等待线程,唤醒线程是随机选择的取决于JVM的实现。唤醒后的线程不能立即执行,需要和其它线程竞争锁。

Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation. A thread waits on an object's monitor by calling one of the wait methods.

The awakened thread will not be able to proceed until the current thread relinquishes the lock on this object. The awakened thread will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened thread enjoys no reliable privilege or disadvantage in being the next thread to lock this object.

This method should only be called by a thread that is the owner of this object's monitor. A thread becomes the owner of the object's monitor in one of three ways:

By executing a synchronized instance method of that object.

By executing the body of a synchronized statement that synchronizes on the object.

For objects of type Class, by executing a synchronized static method of that class.

Only one thread at a time can own an object's monitor.

Throws:

IllegalMonitorStateException – if the current thread is not the owner of this object's monitor.

join()

join是Thread自己实现的方法。也是线程交互的方式之一,可以让别的线程先于自己插队执行,并且自己等待/等待指定时间 让别的线程执行完毕,自己再执行。使用方式:Thread a = new Tread(task) a.start() a.join(),这个时候主线程就会让a先执行完毕。

// 获取等待线程的对象锁

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");

    }

// millis == 0 是不计时等待

    if (millis == 0) {

// 判断等待线程是否存活

        while (isAlive()) {

// 等待线程存活则自己进入等待线程的对象锁的wait池不计时等待

            wait(0);

        }

    } else {

// 计时等待,每次唤醒后判断join线程是否存活

        while (isAlive()) {

            long delay = millis - now;

            if (delay <= 0) {

                break;

            }

            wait(delay);

            now = System.currentTimeMillis() - base;

        }

    }

}

sleep()

sleep()也是native方法,睡眠指定的时间在此期间线程不再被OS调度。但是在此期间不会释放线程持有的任何监视器的锁。sleep()响应interrupt(),在休眠期间如果被中断会抛出异常。或者被中断后进入sleep同样抛出异常。

interrupt()

也是依靠JVM的native方法,给线程的中断标志位开启,中断线程的所有阻塞操作。阻塞的线程会抛出InterruptedException。除此外不会对线程造成任何直接影响。不会真正中断线程,需要线程自己检查标志位。可以用来做线程安全终止的用途。 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值