首页 > 编程语言 >java 线程等待和唤醒方法

java 线程等待和唤醒方法

时间:2023-07-09 23:13:53浏览次数:35  
标签:java Thread threadA System 线程 println 唤醒 out

java线程状态变迁图

从图中可以看出Java 线程等待方法是将线程从Runnable状态转换为Waiting状态,Java线程的唤醒方法是将线程从Waiting状态唤醒进入Runnable状态
在Java中线程的等待和唤醒主要是分为3组:

  • Object.wait() 和 Object.notify()
  • LockSupport.park() 和 LockSupport.unpark(Thread thread)
  • Condition.await() 和 Condition.signal() ---- 这组内部靠LockSupport.park() 和 LockSupport.unpark(Thread thread) 进行线程等待和唤醒

Object.wait() 和 Object.notify()

wait() 和 notify() 相关方法


表中的方法必须要在获得监视器monitor的情况下使用

简单使用wait()和notify()方法示例:

public class WaitTest {

    private static Object object = new Object();

    public static void main(String[] args) throws InterruptedException {
        Thread threadA = new Thread(() -> {
            synchronized (object) {
                try {
                    System.out.println("threadA 已进入获得监视器");
                    object.wait();
                    System.out.println("threadA 已被唤醒");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "threadA");
        threadA.start();
        Thread.sleep(1000);
        synchronized (object){
            System.out.println("main 已获得监视器");
            object.notify();
        }
    }
}

notify()和notifyAll()的区别演示:使用notify() 只能唤醒一个在对象上等待的线程,使用notifyAll()可以唤醒所有在对象上等待的线程。

使用notify()

public class WaitTest {

    private static Object object = new Object();

    public static void main(String[] args) throws InterruptedException {
        Thread threadA = new Thread(() -> {
            synchronized (object) {
                try {
                    System.out.println("threadA 已进入获得监视器");
                    object.wait();
                    System.out.println("threadA 已被唤醒");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "threadA");

        Thread threadB = new Thread(() -> {
            synchronized (object) {
                try {
                    System.out.println("threadB 已进入获得监视器");
                    object.wait();
                    System.out.println("threadB 已被唤醒");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "threadB");
        threadA.start();
        threadB.start();
        Thread.sleep(1000);
        synchronized (object){
            System.out.println("main 已获得监视器");
            object.notify();
            System.out.println("main 已唤醒一个线程");
        }
    }
}


结果线程B未能被唤醒。

改用notifyAll()

public class WaitTest {

    private static Object object = new Object();

    public static void main(String[] args) throws InterruptedException {
        Thread threadA = new Thread(() -> {
            synchronized (object) {
                try {
                    System.out.println("threadA 已进入获得监视器");
                    object.wait();
                    System.out.println("threadA 已被唤醒");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "threadA");

        Thread threadB = new Thread(() -> {
            synchronized (object) {
                try {
                    System.out.println("threadB 已进入获得监视器");
                    object.wait();
                    System.out.println("threadB 已被唤醒");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "threadB");
        threadA.start();
        threadB.start();
        Thread.sleep(1000);
        synchronized (object){
            System.out.println("main 已获得监视器");
            object.notifyAll();
            System.out.println("main 已唤醒一个线程");
        }
    }
}


线程A,B都被唤醒了,程序正常结束。

wait(long) 方法的使用: 等待时间过了没被唤醒自己进入Runnable状态

public class WaitTest {

    private static Object object = new Object();

    public static void main(String[] args) throws InterruptedException {
        Thread threadA = new Thread(() -> {
            synchronized (object) {
                try {
                    System.out.println("threadA 已进入获得监视器");
                    object.wait(1000 * 60);
                    System.out.println("threadA 已被唤醒");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "threadA");
        threadA.start();
    }
}

程序执行结果

调用wait(long) 方法进入timed_waiting状态

等待时间过了进入runnable状态

注意线程中断也会唤醒wait()中的线程

public class WaitTest {

    private static Object object = new Object();

    public static void main(String[] args) throws InterruptedException {
        Thread threadA = new Thread(() -> {
            synchronized (object) {
                try {
                    System.out.println("threadA 已进入获得监视器");
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("threadA 已被唤醒");
            }
        }, "threadA");
        threadA.start();
        Thread.sleep(1000);
        threadA.interrupt();
    }
}

程序执行结果

LockSupport.park() 和 LockSupport.unpark(Thread thread)

LockSupport.park() 和 LockSupport.unpark(Thread thread) 并不依赖同步方法

LockSupport.park() 和 LockSupport.unpark(Thread thread) 相关方法

简单使用

public class ParkTest {

    public static void main(String[] args) throws InterruptedException {
        Thread threadA = new Thread(() -> {
            System.out.println("ThreadA 开始运行了");
            LockSupport.park();
            System.out.println("ThreadA 继续运行了");
        }, "ThreadA");
        threadA.start();
        Thread.sleep(1000 * 5);
        LockSupport.unpark(threadA);
    }
}

注意线程中断也会唤醒LockSupport.park()中的线程

public class ParkTest {

    public static void main(String[] args) throws InterruptedException {
        Thread threadA = new Thread(() -> {
            System.out.println("ThreadA 开始运行了");
            LockSupport.park();
            System.out.println("ThreadA 继续运行了");
        }, "ThreadA");
        threadA.start();
        Thread.sleep(1000 * 5);
        threadA.interrupt();
    }
}

Condition.await() 和 Condition.signal()

Condition.await() 和 Condition.signal() 相关方法

简单使用

public class ConditionTest {

    static Lock lock = new ReentrantLock();
    static Condition condition = lock.newCondition();
    public static void main(String[] args) throws InterruptedException {
        Thread threadA = new Thread(() -> {
            lock.lock();
            try {
                System.out.println("线程A 获得了lock锁");
                condition.await();
            } catch (InterruptedException e) {
                System.out.println("线程A 被唤醒了");
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }, "ThreadA");
        threadA.start();
        Thread.sleep(1000 * 5);
        lock.lock();
        try {
            System.out.println("main 线程获得了lock锁");
            condition.signal();
        } catch (Exception e){
            e.printStackTrace();
        } finally {
          lock.unlock();
        }
    }
}

程序执行结果:

注意线程中断也会唤醒condition.await()中的线程

public class ConditionTest {

    static Lock lock = new ReentrantLock();
    static Condition condition = lock.newCondition();
    public static void main(String[] args) throws InterruptedException {
        Thread threadA = new Thread(() -> {
            lock.lock();
            try {
                System.out.println("线程A 获得了lock锁");
                condition.await();
            } catch (InterruptedException e) {
                System.out.println("线程A 被唤醒了");
                e.printStackTrace();
            } finally {
                lock.unlock();
            }
        }, "ThreadA");
        threadA.start();
        Thread.sleep(1000 * 5);
        threadA.interrupt();
        condition.signal();
    }
}

程序执行结果:

Condition.signalAll() 用法上和Object.notifyAll() 类似

参考:《Java并发编程的艺术》

标签:java,Thread,threadA,System,线程,println,唤醒,out
From: https://www.cnblogs.com/yuyiming/p/17539424.html

相关文章

  • Java自签名证书的信任处理
    一、概要1.问题的由来该问题是由于Java访问的域名是https且使用了自签名证书,Java客户端无法验证证书的合法性,进而报出异常。该问题有以下解决思路:a.在Java客户端忽略证书的校验,这种方式适用于自己掌握Code的情况,且客户端服务端处于互相信任的环境中;b.将服务端的自签名证......
  • 【java】数组的常用操作
    sortstaticvoidsort(int[]a):将a数组按照从小到大进行排序staticvoidsort(int[]a,intfromIndex,inttoIndex):将a数组的[fromIndex,toIndex)部分按照升序排列staticvoidsort(Object[]a):根据元素的自然顺序对指定对象数组按升序进行排序。static<T>voidsort(T......
  • 暗黑2能用Java开发?还能生成APP?
    最近烧哥发现个宝藏项目,竟然用Java开发了暗黑2出来。众所周知,暗黑2是暴雪开发的一款经典游戏,距今虽有20多年,仍然有很多粉丝。粉丝延续热情的方式有很多,一种是做Mod,比如魔电,对怪物、技能、物品、场景、甚至游戏机制都有大改,目前还在定期更新,并有战网提供。另一种是纯怀旧,用另......
  • 03线程安全
    线程安全发生的终极原因是:内存,寄存器存在时间差。今天突然想到一个很好的例子 解释这个问题:一堂随堂测试,你正在答一道题,老师巡考看到你的答案是正确的,其他同学全部是错误的。晚上老师说道这次考试这道题只有一个同学做对了。但是老师不知道你在他走后,修改了答案。最终考试试卷......
  • Java虚拟机(JVM):第四幕:自动内存管理 - 经典垃圾收集器
    前言:如果说收集算法是内存回收的方法论,那么垃圾收集器则是内存回收的实践者。整哥Java堆:FullGC。1、Serial收集器:最基础、历史最悠久的收集器,这是一个单线程工作的收集器。2、ParNew收集器:是Serial收集器的多线程并行版本,可以说是跟Serial完全一样。CMS收集......
  • 开心档之Java 测验
    目录Java测验 Java测验Java测验技术文档Java测验是一种衡量Java编程水平的测试,可以通过一系列问题和编程任务来测试Java开发人员的技能水平和理解程度。Java测验可以用于聘用程序员、衡量编程实践水平和掌握Java的程度。Java测验通常涵盖以下主题:基本语法-测试Ja......
  • Java - JavaWeb - Concepts
    1.Servlet配置1.1.配置父级项目配置好IntellijIDEA/MAVEN之后, 创建一个新项目com.crevew.javaweb-02-servlet,然后删除所有的SRC(方便接下来创建servlet模块);然后更新最外面的父pom.xml,加上<projectxmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.......
  • 线程池excute方法执行流程
    1//线程池execute方法执行流程2publicvoidexecute(Runnablecommand){3//非空判断,判断提交的任务是否为空4if(command==null)5thrownewNullPointerException();6//获取ctl属性7intc=ctl.get......
  • 线程创建
    三种创建方式Threadclass继承Thread类Runnable接口实现Runnable接口Callable接口实现Callable接口Thread自定义线程类继承Thread类重写run()方法,编写线程执行体创建线程对象,调用start()方法启动线程//创建线程方式一:继承Thread类,重写run()......
  • String内存模型和Java常用方法
    一、String内存模型1、直接赋值创建string对象内存原理:StringTable(串池):字符串常量池,用来存储字符串,只能是在直接赋值中使用才会存在串池当中(JDK7前串池是在方法区里面,StringTable(串池)在JDK7版本开始从方法区中挪到了堆内存,但是运行机制没有发生变化)eg:首先mian方法进栈,创建变......