wait线程阻塞

介绍

线程阻塞通常是指一个线程在执行过程中由于某种原因从运行状态转为暂停状态的过程,线程阻塞会放弃CPU的使用权, 并且等待某个条件重新从暂停状态改为就绪状态。在Java中,通常使用object.wait让线程进入阻塞状态。

使用

首先我们先看wait方法,wait方法总共有三个重载方法,分别是 wait() wait(long timeout) wait(long timeout, int nanos),其中wait方法内部是调用了wait(0),顾名思义timeout就是超时时间,那么timeout等于0是什么意思呢,查看官方API如下:

意思就是如果timeout是0,不需考虑超时时间,即线程会无限等待直到被唤醒。
下面写一个demo,代码如下:

    public static void main(String args[]) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println( "执行线程中");
            }
        });
        thread.setName("MyThread");
        thread.start();
        
        try{
            thread.wait();
        }catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(thread.getName() + "已经执行结束");
    }
复制代码

预想的输出结果应该是

执行线程中
MyThread已经执行结束
复制代码

实际上报错了

Exception in thread "main" java.lang.IllegalMonitorStateException
复制代码

查看wait的API介绍有这么一句标注 The current thread must own this object's monitor.,大意就是执行wait方法的线程必须持有线程的对象锁,使用synchronized对thread对象加锁既可,代码如下:

        try{
            synchronized (thread) {
                thread.wait();
            }
        }catch (InterruptedException e) {
            e.printStackTrace();
        }
复制代码

这样一来,通过synchronize既可获取线程的对象锁,就可以达到阻塞线程的作用了,有人可能会疑惑说为什么没有调用notify方法,这是因为当线程死亡之后,相应的wait方法也会失效。

当然对于线程的阻塞,通用使用线程的join方法,代码如下:

    public static void main(String args[]) {
        Thread thread1 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println( "执行线程1中");
            }
        });
        thread1.setName("MyThread -- 1");
        thread1.start();

        Thread thread2 = new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println( "执行线程2中");
            }
        });
        thread2.setName("MyThread -- 2");
        thread2.start();

        try{
            thread1.join();
            thread2.join();
        }catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(thread1.getName() + " " + thread2.getName()  + "  已经执行结束");
    }
复制代码

通过调用join方法,就可以让线程阻塞,我们看一下join的方法实现:

    public final synchronized void join(long var1) throws InterruptedException {
        long var3 = System.currentTimeMillis();
        long var5 = 0L;
        if (var1 < 0L) {
            throw new IllegalArgumentException("timeout value is negative");
        } else {
            if (var1 == 0L) {
                while(this.isAlive()) {
                    this.wait(0L);
                }
            } else {
                while(this.isAlive()) {
                    long var7 = var1 - var5;
                    if (var7 <= 0L) {
                        break;
                    }

                    this.wait(var7);
                    var5 = System.currentTimeMillis() - var3;
                }
            }

        }
    }
复制代码

其实就是当线程还存活时,调用wait方法。需要注意的是,join方法是synchronize的,因为需要获取对象锁。

参考

Wait方法的官方API介绍

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值