线程中的join()、wait() 和 notify()详解及练习题

news2024/11/26 16:57:20

一、join()

Thread提供了 join() 方法,用于等待当前线程所调用的其他线程执行完毕。

1、当一个线程调用另一个线程的 join() 方法时,它会被阻塞,直到被调用的线程执行完毕或达到指定的超时时间。

比如:当主线程main中调用了另一个线程thread1,那么main线程会被阻塞,只有当thread1执行完毕,main线程才继续执行。

2、当然也可以调用join() 方法还有一个重载的形式,允许指定等待的最大时间:

public final synchronized void join(long millis) throws InterruptedException

在上述形式中,millis 参数表示等待的最大时间,以毫秒为单位。如果被调用的线程在指定的时间内没有执行完毕,当前线程将不再等待,继续执行后续的操作。

join() 方法通常用于实现线程之间的协作和同步。例如,可以创建多个线程,然后使用 join() 方法来确保这些线程按照特定的顺序执行。

练习1:要求线程a执行完才开始线程b, 线程b执行完才开始线程c

import org.junit.Test;

/**
 * @Author xpf
 * @Date 2023/9/5 17:07
 * @Version 1.0
 *  要求线程a执行完才开始线程b, 线程b执行完才开始线程c
 */
public class MyThreadJoin {

    public static class MyThread extends Thread{

        MyThread(String name){
            super(name);
        }

        @Override
        public void run() {
            for (int i= 1; i <= 10; i++){
                System.out.println(getName() + ":" + i);
            }
        }
    }

    //https://blog.csdn.net/shinecjj/article/details/103792151
    public static void main(String[] args) {
        MyThread t1 = new MyThread("a");
        MyThread t2 = new MyThread("b");
        MyThread t3 = new MyThread("c");

        try {
            t1.start();
            t1.join();

            t2.start();
            t2.join();

            t3.start();
            t3.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }


}

结果:

二、wait() 和 notify()

1、wait() 和 notify() 是object对象的方法

2、wait():

可以使当前线程进入等待状态直到其他线程调用 notify() 或者 notifyAll() 方法唤醒它。

在调用 wait() 方法时,当前线程会释放它所持有的锁,以便其他线程可以访问共享资源

 3、notify():

用于唤醒一个处于等待状态的线程,如果有多个线程在等待,则只会唤醒其中一个线程

notifyAll() 方法则会唤醒所有处于等待状态的线程。 

wait和 notify 方法必须在同步块中使用,即在使用这两个方法的对象上获取锁。否则会抛出illegalMonitorStateException异常

练习1:两个线程轮流打印数字,一直到100

/**
 * @Author xpf
 * @Date 2023/9/6 10:35
 * @Version 1.0
 * 2、两个线程轮流打印数字,一直到100
 * wait() 和 notify() 是object对象的方法
 * wait():可以使当前线程进入等待状态,直到其他线程调用 notify() 或者 notifyAll() 方法唤醒它。
 *         在调用 wait() 方法时,当前线程会释放它所持有的锁,以便其他线程可以访问共享资源
 * notify():用于唤醒一个处于等待状态的线程,如果有多个线程在等待,则只会唤醒其中一个线程。notifyAll方法则会唤醒所有处于等待状态的线程。
 * wait和 notify 方法必须在同步块中使用,即在使用这两个方法的对象上获取锁。否则会抛出illegalMonitorStateException异常
 */
public class ThreadWaitNotify {

     static class TakeTurnsAdd{
        final Object lock = new Object();
        boolean getFlag = true;
        int sum = 1;
        public void add1(){
            synchronized (lock){
                String threadName = Thread.currentThread().getName();
                for (int i = 1; i <= 50; i++) {
                    if (getFlag){
                        try {
//                            System.out.println(threadName + "wait()前" );
                            lock.wait();
//                            System.out.println(threadName + "wait()后" );
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                    }

                    System.out.println(threadName + "a:" + sum++);
//                    System.out.println(threadName + "notify()前" );
                    getFlag = !getFlag;
                    lock.notify();
//                    System.out.println(threadName + "notify()后" );
                }
            }

        }

        public void add2(){
            synchronized (lock){
                String threadName = Thread.currentThread().getName();
                for (int i = 1; i <= 50; i++) {
                    if (!getFlag){
                        try {
//                            System.out.println(threadName + "wait()前" );
                            lock.wait();
//                            System.out.println(threadName + "wait()后" );
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.println(threadName + "b:" + sum++);
//                    System.out.println(threadName + "notify()前" );
                    getFlag = !getFlag;
                    lock.notify();
//                    System.out.println(threadName + "notify()后" );
                }
            }

        }
    }

    public static void main(String[] args) {
        TakeTurnsAdd takeTurnsAdd = new TakeTurnsAdd();
        new Thread(()->{takeTurnsAdd.add1();}).start();
        new Thread(()->{takeTurnsAdd.add2();}).start();
    }
}

结果:

...

 练习2:两线程,一个打印数字从1到52,另一个打印字母从A到Z,输出:12A34B56C...5152Z

/**
 * @Author xpf
 * @Date 2023/9/6 10:35
 * @Version 1.0
 * 两线程,一个打印数字从1到52,另一个打印字母从A到Z,输出:12A34B56C...5152Z
 */
public class ThreadWaitNotify2 {

     static class TakeTurnsAdd{
        final Object lock = new Object();
        boolean getFlag = false;
        int sum = 1;
        public void add1(){
            synchronized (lock){
                String threadName = Thread.currentThread().getName();
                for (int i = 1; i <= 26; i++) {
                    if (getFlag){
                        try {
//                            System.out.println(threadName + "wait()前" );
                            lock.wait();
//                            System.out.println(threadName + "wait()后" );
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }

                    }
                    System.out.print(sum++);
                    System.out.print(sum++);
//                    System.out.println(threadName + "notify()前" );
                    getFlag = !getFlag;
                    lock.notify();
//                    System.out.println(threadName + "notify()后" );
                }
            }

        }

        public void add2(){
            synchronized (lock){
                String threadName = Thread.currentThread().getName();
                for (int i = 0; i < 26; i++) {
                    if (!getFlag){
                        try {
//                            System.out.println(threadName + "wait()前" );
                            lock.wait();
//                            System.out.println(threadName + "wait()后" );
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    System.out.print((char) (65+i));
//                    System.out.println(threadName + "notify()前" );
                    getFlag = !getFlag;
                    lock.notify();
//                    System.out.println(threadName + "notify()后" );
                }
            }

        }
    }

    public static void main(String[] args) {
        TakeTurnsAdd takeTurnsAdd = new TakeTurnsAdd();
        new Thread(()->{takeTurnsAdd.add1();}).start();
        new Thread(()->{takeTurnsAdd.add2();}).start();
    }
}

结果:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/980018.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

手把手教会如何掌握Swagger

文章目录 前言一、Swagger重要组件及作用二、SpringBoot集成Swagger1.环境准备2.配置Swagger3.配置Swagger扫描接口4.配置API分组5.拓展&#xff1a;其他皮肤 三、常用注解1.接口注解2.方法及参数注解3.实体类注解效果如图&#xff1a; ![在这里插入图片描述](https://img-blog…

面向未来的编程方式,做为开发者,很必要了解一下什么是iVX

面向未来的编程方式&#xff0c;做为开发者&#xff0c;很必要了解一下什么是iVX 一前言二什么是传统低代码平台以及传统平台的局限性和作用1.什么是传统低代码平台2.传统平台的局限性 三为什么程序员和技术管理者不太可能接受“低代码”平台&#xff1f;1.低代码的特征2.为什么…

【C++基础】4. 变量

文章目录 【 1. 变量的定义 】【 2. 变量的声明 】示例 【 3. 左值和右值 】 变量&#xff1a;相当于是程序可操作的数据存储区的名称。在 C 中&#xff0c;有多种变量类型可用于存储不同种类的数据。C 中每个变量都有指定的类型&#xff0c;类型决定了变量存储的大小和布局&am…

Windows server 2012安装IIS的方法

Windows Server 2012是微软公司研发的服务器操作系统&#xff0c;于2012年9月4日发布。 Windows Server 2012可以用于搭建功能强大的网站、应用程序服务器与高度虚拟化的云应用环境&#xff0c;无论是大、中或小型的企业网络&#xff0c;都可以使用Windows Server 2012的管理功…

*** error 65: access violation at 0xFFFFFFF4 : no ‘write‘ permission怎么办

我发现是我的单片机型号设置错了&#xff0c;把debug里面的STM32F103ZET6修改为STM32F103ZE就可以正常运行了

信息检索度量指标(MAP@N, P@N)

我们今天遇到的大多数软件产品都集成了某种形式的搜索功能。我们在谷歌上搜索内容&#xff0c;在YouTube上搜索视频&#xff0c;在亚马逊上搜索产品&#xff0c;在Slack上搜索信息&#xff0c;在Gmail上搜索邮件&#xff0c;在Facebook上搜索人等等。 作为用户&#xff0c;工作…

基于SSM+Vue的网上花店系统

末尾获取源码 开发语言&#xff1a;Java Java开发工具&#xff1a;JDK1.8 后端框架&#xff1a;SSM 前端&#xff1a;采用Vue技术开发 数据库&#xff1a;MySQL5.7和Navicat管理工具结合 服务器&#xff1a;Tomcat8.5 开发软件&#xff1a;IDEA / Eclipse 是否Maven项目&#x…

【问题总结】 记 一次dockerFile构建报错

写在前面&#xff0c; 其实是一个比较摸不着脑袋的bug&#xff0c;记录一下解决的过程&#xff0c;作为备忘录 问题留档 1、场景描述 在尝试使用dockefile构建一个tomcat镜像&#xff0c;内容如下&#xff0c;构建正常通过&#xff0c;但是容器启动失败 FROM centos:7 MAINT…

【办公类-18-02】(Python)教师获奖证书批量打印(教师信息、获奖类型,公章)

背景需求&#xff1a; 同事提出给word批量“添加电子公章&#xff08;png图片&#xff09;的需求 解压文件后&#xff0c;发现&#xff1a; 1、每份WORD文件名是一位老师的证书&#xff0c;需要打开每一份word&#xff0c;插入一个空白电子公章png。 2、每个word文件名包含教…

Redis缓存的高并发问题

Redis 做缓存虽减轻了 DBMS 的压力&#xff0c;减小了 RT&#xff0c;但在高并发情况下也是可能会出现各 种问题的。 1 缓存穿透 当用户访问的数据既不在缓存也不在数据库中时&#xff0c;就会导致每个用户查询都会“穿透” 缓存“直抵”数据库。这种情况就称为缓存穿透。一个…

SSL证书系列--又拍云Let’s Encrypt免费DV SSL证书使用教程

原文网址&#xff1a;SSL证书系列--又拍云Let’s Encrypt免费DV SSL证书使用教程_IT利刃出鞘的博客-CSDN博客 简介 本文介绍如何使用又拍云部署Let’s Encrypt免费DV SSL证书。 一、了解Let’s Encrypt 了解和关注SSL证书的朋友&#xff0c;似乎没有理由不知道 Let’s Encr…

java八股文面试[数据库]——数据库锁的种类

数据库锁的种类 MySQL数据库由于其自身架构的特点,存在多种数据存储引擎, MySQL中不同的存储引擎支持不同的锁机制。 MyISAM和MEMORY存储引擎采用的表级锁&#xff0c; InnoDB存储引擎既支持行级锁&#xff0c;也支持表级锁&#xff0c;默认情况下采用行级锁。 BDB采用的是页…

开店星小程序上架教程和后台Request failed with status code 500[undefined]问题处理

开店星小程序上架教程和后台Request failed with status code 500[undefined]问题处理 刚刚安装好开店星网站后台之后都会出现这个code 500[undefined]的错误&#xff0c;需要改一下代码。改好了之后就可以正常使用了。如果大家不懂得这样处理的可以私聊我&#xff0c;帮忙处理…

kettle通过java步骤获取汉字首拼

kettle通过java步骤获取汉字首拼 用途描述 一组数据&#xff0c;需要获取汉字首拼后&#xff0c;输出&#xff1b; 实现效果 添加jar包 pinyin4j-2.5.0.jar 自定义常量数据 Java代码 完整代码&#xff1a; import net.sourceforge.pinyin4j.PinyinHelper; import net.sou…

高潮迭起:探寻Twitch上精彩纷呈的电子竞技赛事直播

Twitch是电子竞技赛事的热门直播平台之一,它为全球范围内的电子竞技比赛提供了广泛的覆盖和直播服务。以下是一些在Twitch上直播的电子竞技比赛和赛事的例子: League of Legends (英雄联盟) Twitch广泛直播英雄联盟的各个赛事,包括全球性的锦标赛如英雄联盟全球总决赛(World …

SLAM从入门到精通(基本框架)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 SLAM是机器人的一个分支。广义上来说&#xff0c;机器人还包括了计算机视觉、语音识别、自然语言处理、机械臂控制、运动控制、机器人导航、机器人…

软件架构师 设计和编码

软件架构师 设计和编码 目录概述需求&#xff1a; 设计思路实现思路分析1.设在设计软件架构时&#xff0c;您需要考虑以下方面&#xff1a;2.在编码方面&#xff0c;您需要具有以下技能&#xff1a; 参考资料和推荐阅读 Survive by day and develop by night. talk for import …

如何绘制英语思维导图?偷偷告诉你这个绘制方法

如何绘制英语思维导图&#xff1f;绘制英语思维导图可以帮助我们更好地理清思路&#xff0c;提高学习和工作效率。同时&#xff0c;英语思维导图还可以帮助我们提高英语表达能力和阅读理解能力&#xff0c;让我们更好地掌握英语学习和应用。因此&#xff0c;绘制英语思维导图是…

msvcr120.dll放在哪里?怎么修复msvcr120.dll文件

当您在运行某些应用程序或游戏时遇到“msvcr120.dll缺失”错误时&#xff0c;这可能会影响您的使用体验。msvcr120.dll是Microsoft Visual C Redistributable的一部分&#xff0c;并且它提供了程序运行所需的运行时支持&#xff0c;今天我们来讨论一下msvcr120.dl文件缺失了要怎…

[SSM]MyBatisPlus高级

四、高级篇 4.1主键策略 主键的作用就是唯一标识&#xff0c;我们可以通过这个唯一标识来定位到这条数据。对于表数据中的主键&#xff0c;我们可以自己设计生成规则&#xff0c;生成主键。但是在更多的场景中&#xff0c;没有特殊要求的话&#xff0c;我们每次自己手动生成的…