• 三、等待与唤醒


    在Object.java中,定义了wait(), notify()和notifyAll()等接口。

    notify()        -- 唤醒在此对象监视器上等待的单个线程。
    notifyAll()   -- 唤醒在此对象监视器上等待的所有线程。
    wait()                                         -- 让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法”,当前线程被唤醒(进入“就绪状态”)。
    wait(long timeout)                    -- 让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者超过指定的时间量”,当前线程被唤醒(进入“就绪状态”)。
    wait(long timeout, int nanos)  -- 让当前线程处于“等待(阻塞)状态”,“直到其他线程调用此对象的 notify() 方法或 notifyAll() 方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量”,当前线程被唤醒(进入“就绪状态”)。

    注意:1.wait()和notify()必须在synchronized块里面使用

    2.调用wait()和notify()的对象必须与synchronized块锁对象一致。

    wait()的作用是让当前线程进入等待状态,同时,wait()也会让出当前线程释放它所持有的锁。而 notify()和notifyAll()的作用,则是唤醒当前对象上的等待线程;notify()是唤醒单个线程,而notifyAll()是唤醒所有 的线程。

    public class WaitTest {
        
        public static void main(String[] args) {
            final Atest a = new Atest();
            Runnable runnable = new Runnable(){
                @Override
                public void run() {
                    a.m1();
                }
            };
            /**
             * 经测试调用wait()方法当前线程会处于等待状态,而且会释放它所持有的锁。
             */
            Thread t1 = new Thread(runnable);
            Thread t2 = new Thread(runnable);
            t1.start();
            try {
                /**
                 * 当t1线程执行完,主线程才能继续执行。
                 * 如果t1处于等待状态,主线程也无法往下执行,因为t1只是处于等待状态,而未执行完。
                 */
                t1.join();    
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            t2.start();
        }
        
    }
    
    class Atest{
        boolean flag = true;
        public synchronized void m1(){
            System.out.println("m1方法开始"+Thread.currentThread());
            while(flag){
                try {
                    this.wait(10000);
    //                this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                flag = false;
            }
            System.out.println("m1方法结束"+Thread.currentThread());
        }
    }

    这里说一下Thread类的join()方法:

    join() 的作用:让“主线程”等待“该线程”结束之后才能继续运行,这里说的主线程是相对于该线程而言的,并不是指定main线程。

    package com.fla.thread;
    
    public class NotifyTest {
        public static void main(String[] args) {
            final Ntest n = new Ntest();
            Runnable run1 = new Runnable(){
                @Override
                public void run() {
                    n.m1();
                }
            };
            Thread t1 = new Thread(run1);
            Thread t2 = new Thread(run1);
            Thread t3 = new Thread(new Runnable() {
                @Override
                public void run() {
                    n.m2();
                }
            });
            t1.start();
            t2.start();
            t3.start();
        }
    }
    
    class Ntest {
        boolean flag = true ;
        public synchronized void m1(){
            System.out.println("m1方法开始"+Thread.currentThread()+",锁对象hashcode:");
            while(flag){
                try {
                    this.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("m1方法结束"+Thread.currentThread()+",锁对象hashcode:");
        }
        
        public synchronized void m2(){
            System.out.println("m2方法开始"+Thread.currentThread()+",锁对象hashcode:");
    //        this.notifyAll();
            this.notify();
            flag = false ;
        }
    }

    notify()是唤醒在此对象(与同步块锁对象一致)监视器上等待的单个线程。,而notifyAll()是唤醒在此对象监视器上等待的所有线程。

    wait() 和 sleep()的差别:

    wait() 让当前线程处于“等待(阻塞)状态”,也会让出当前线程释放它所持有的锁,不占cpu资源。

    sleep()  让线程睡眠一段时间,占着cpu进入睡眠,如果在同步代码块里面,也不会释放所持有的锁

    这里顺便说一下Thread类的yield()方法。

    yield()的作用是让步。它能让当前线程由“运行状态”进入到“就绪状态”,从而让 其它具有相同优先级的等待线程获取执行权;但是,并不能保证在当前线程调用yield()之后,其它具有相同优先级的线程就一定能获得执行权;也有可能是 当前线程又进入到“运行状态”继续运行!

  • 相关阅读:
    Qt之添加QLabel的点击事件
    Qt之布局管理--基本布局
    Qt之界面实现技巧
    Qt之键盘讲解
    Qt之多窗口切换
    Qt之自定义信号和槽函数
    Qt之重写QLabel类
    mysql学习(四)-字段类型
    mysql学习(三)
    mysql 复习与学习(二)数据库及表结构的创建删除
  • 原文地址:https://www.cnblogs.com/futiansu/p/5619024.html
Copyright © 2020-2023  润新知