对并发熟悉吗?谈谈线程间的协作(wait/notify/sleep/yield/join)

本文详细探讨了Java中线程的状态转换,重点解析了wait/notify/notifyAll、sleep、yield和join方法的使用。线程状态包括New、Runnable、Running、Blocked和Dead。wait方法需在同步块中调用,否则会抛出异常,用于线程等待;notify/notifyAll用于唤醒等待的线程,notify仅唤醒一个,notifyAll唤醒所有。sleep让线程暂停指定时间,不释放锁;yield让当前线程暂停,让其他线程有机会执行;join使父线程等待子线程完成。
摘要由CSDN通过智能技术生成

一、线程的状态

Java中线程中状态可分为五种:New(新建状态),Runnable(就绪状态),Running(运行状态),Blocked(阻塞状态),Dead(死亡状态)。

  • New:新建状态,当线程创建完成时为新建状态,即new Thread(…),还没有调用start方法时,线程处于新建状态。

  • Runnable:就绪状态,当调用线程的的start方法后,线程进入就绪状态,等待CPU资源。处于就绪状态的线程由Java运行时系统的线程调度程序(thread scheduler)来调度。

  • Running:运行状态,就绪状态的线程获取到CPU执行权以后进入运行状态,开始执行run方法。

  • Blocked:阻塞状态,线程没有执行完,由于某种原因(如,I/O操作等)让出CPU执行权,自身进入阻塞状态。

  • Dead:死亡状态,线程执行完成或者执行过程中出现异常,线程就会进入死亡状态。

这五种状态之间的转换关系如下图所示:

有了对这五种状态的基本了解,现在我们来看看Java中是如何实现这几种状态的转换的。 

二、wait/notify/notifyAll方法的使用

1、wait方法:

JDK中一共提供了这三个版本的方法,

  • wait()方法的作用是将当前运行的线程挂起(即让其进入阻塞状态),直到notify或notifyAll方法来唤醒线程.

  • wait(long timeout),该方法与wait()方法类似,唯一的区别就是在指定时间内,如果没有notify或notifAll方法的唤醒,也会自动唤醒。

  • 至于wait(long timeout,long nanos),本意在于更精确的控制调度时间,不过从目前版本来看,该方法貌似没有完整的实现该功能,其源码(JDK1.8)如下:

public final void wait(long timeout, int nanos) throws InterruptedException {
        if (timeout < 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 && timeout == 0)) {
            timeout++;
        }

        wait(timeout);
    }

从源码来看,JDK8中对纳秒的处理,只做了四舍五入,所以还是按照毫秒来处理的,可能在未来的某个时间点会用到纳秒级别的精度。虽然JDK提供了这三个版本,其实最后都是调用wait(long timeout)方法来实现的,wait()方法与wait(0)等效,而wait(long timeout,int nanos)从上面的源码可以看到也是通过wait(long timeout)来完成的。

下面我们通过一个简单的例子来演示wait()方法的使用:

package com.paddx.test.concurrent;

public class WaitTest {

    public void testWait(){
        System.out.println("Start-----");
        try {
            wait(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("End-------");
    }

    public static void main(String[] args) {
        final WaitTest test = new WaitTest();
        new Thread(new Runnable() {
            @Override
            public void run() {
                test.testWait();
            }
        }).start();
    }
}

这段代码的意图很简单,就是程序执行以后,让其暂停一秒,然后再执行。运行上述代码,查看结果:

Start-----
Exception in thread "Thread-0" java.lang.IllegalMonitorStateException
    at java.lang.Object.wait(Native Method)
    at com.paddx.test.concurrent.WaitTest.testWait(WaitTest.java:8)
    at com.paddx.test.conc
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值