sleep和wait区别,并且查看线程运行状态

news2024/11/23 16:55:05

一、sleep和wait区别

区别一:语法使用不同

wait 方法必须配合 synchronized 一起使用,不然在运行时就会抛出 IllegalMonitorStateException 的异常

而 sleep 可以单独使用,无需配合 synchronized 一起使用。

区别二:所属类不同

wait 方法属于 Object 类的方法,而 sleep 属于 Thread 类的方法

区别三:唤醒方式不同

sleep 方法必须要传递一个超时时间的参数,且过了超时时间之后,线程会自动唤醒。而 wait 方法可以不传递任何参数,不传递任何参数时表示永久休眠,直到另一个线程调用了 notify 或 notifyAll 之后,休眠的线程才能被唤醒。也就是说 sleep 方法具有主动唤醒功能,而不传递任何参数的 wait 方法只能被动的被唤醒

区别四:释放锁资源不同

wait 方法会主动的释放锁,而 sleep 方法则不会。接下来我们使用代码的方式来演示一下二者的区别。

sleep 不释放锁

接下来使用 sleep 是线程休眠 2s,然后在另一个线程中尝试获取公共锁,如果能够获取到锁,则说明 sleep 在休眠时会释放锁,反之则说明不会释放锁,

在调用了 sleep 之后,在主线程里尝试获取锁却没有成功,只有 sleep 执行完之后释放了锁,主线程才正常的得到了锁,这说明 sleep 在休眠时并不会释放锁。

wait 释放锁

接下来使用同样的方式,将 sleep 替换成 wait,在线程休眠之后,在另一个线程中尝试获取锁,

当调用了 wait 之后,主线程立马尝试获取锁成功了,这就说明 wait 休眠时是释放锁的

区别五:线程进入状态不同

调用 sleep 方法线程会进入 TIMED_WAITING 有时限等待状态,而调用无参数的 wait 方法,线程会进入 WAITING 无时限等待状态。

总结

sleep 和 wait 都可以让线程进入休眠状态,并且它们都可以响应 interrupt 中断,但二者的区别主要体现在:语法使用不同、所属类不同、唤醒方式不同、释放锁不同和线程进入的状态不同。 ​

二、线程的状态Thread.State

三、供参考的多线程代码一、sleep和wait(WAITING和TIMED_WAITING状态)


public class Test04_ThreadState {

    public static void main(String[] args) {
        new Thread(new TimeWaiting(), "TimeWaitingThread").start();
        new Thread(new Waiting(), "WaitingThread").start();

    }
    /**
     * 该线程不断的进行睡眠
     */
    static class TimeWaiting implements Runnable {
        @Override
        public void run() {
            while (true) {
                SleepUtils.second(100);
            }
        }
    }
    /**
     * 该线程在Waiting.class实例上等待
     */
    static class Waiting implements Runnable {
        @Override
        public void run() {
            while (true) {
                synchronized (Waiting.class) {
                    try {
                        Waiting.class.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

}

四、查看线程运行状态的方法

1.jps

获得线程号和线程的类名

2.jstack + 线程号

jstack 2636

看线程某个时刻的运行情况(线程的快照)

这里打印出来的是当前线程的快照dump。

3.jvisualvm(可视化软件)

在java的jdk目录下的bin目录下有jvisualvm.exe文件,可以

打开软件后可以看到正在运行的进程,如下图

可以在其中找到java代码创建的线程的名字对应的线程

可以看到WatingThread线程状态是WAITING,等待状态

TimeWaitingThread线程状态是TIMED_WAITING,超时等待状态

和我们这篇文章的  二、线程的状态Thread.State  对应。

五、案例

一、Blocked阻塞状态

Blocked阻塞状态代码


public class Test04_ThreadState {

    public static void main(String[] args) {
        new Thread(new Blocked(), "BlockedThread-1").start();
        new Thread(new Blocked(), "BlockedThread-2").start();
    }
    
    /**
     * 该线程在Blocked.class实例上加锁后,不会释放该锁
     */
    static class Blocked implements Runnable {
        @Override
        public void run() {
            synchronized (Blocked.class) {
                while (true) {
                    SleepUtils.second(100);
                }
            }
        }
    }
}

Blocked阻塞状态代码jvisualvm查看

由于BlockedThread-1先创建,抢占到了系统资源,运行后拿到了锁,并调用了sleep方法,因此进入TIMED_WAITING超时等待状态,而BlockedThread-2拿不到锁,因此进入Blocked阻塞状态。线程快照dump如下图:

Blocked阻塞状态代码总结

1.触发Blocked状态的原因

由于BlockedThread-1先创建,抢占到了系统资源,运行后拿到了锁,并调用了sleep方法,因此进入TIMED_WAITING超时等待状态,而BlockedThread-2拿不到锁,因此进入Blocked阻塞状态。

2.sleep方法

由于sleep方法不会释放锁,因此BlockedThread-2无法拿到锁,进入阻塞状态,更加验证了sleep方法不会释放锁。

二、ReentrantLock可重入锁

ReentrantLock可重入锁代码


public class Test04_ThreadState {

    private static Lock lock = new ReentrantLock();

    public static void main(String[] args) {
        new Thread(new Sync(), "SyncThread-1").start();
        new Thread(new Sync(), "SyncThread-2").start();
    }
   
    static class Sync implements Runnable {

        @Override
        public void run() {
            lock.lock();
            try {
                SleepUtils.second(100);
            } finally {
                lock.unlock();
            }
        }

    }
}

ReentrantLock可重入锁代码jvisualvm查看

ReentrantLock可重入锁代码总结

1.synchronized和ReentrantLock区别(简略描述,之后会详细补充)

ReentrantLock锁更加面向对象
两个锁加锁之后另外一个线程进入状态不一样
synchronized进入blocked状态是被动的 还没有进入到同步代码块中
ReentrantLock是一种主动进入锁的状态 已经进入到代码块中 程序恢复之后 它会从等待的位置继续执行

最后总结:

        a.线程的状态 
            jps看线程的线程号
            jstack看线程某个时刻的运行情况(线程的快照)
            jvisualvm对线程进行dump

        b.线程调用sleep
            进入TimeWaiting状态 不会释放锁
        c.线程调用wait
            进入Waiting状态 会释放锁    
        d.A线程进入B线程已经拿到锁(synchronized)
            A线程会进入阻塞状态blocked状态
        e.当A线程进入B线程已经拿到锁(lock)
            A线程会进入等待状态waiting状态
        f.synchronized和lock区别
            1.lock锁更加面向对象
            2.两个锁加锁之后另外一个线程进入状态不一样:

                synchronized是blocked状态,lock是waiting状态
            3.synchronized进入blocked状态是被动的 还没有进入到同步代码块中
            4.lock是一种主动进入锁的状态 已经进入到代码块中 程序恢复之后 它会从等待的位置继续执行

如果你不太理解synchronized锁的对象是什么,你可以看下面这篇文章:

synchronized锁的对象是什么

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

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

相关文章

【动态规划精选题目】1、斐波那契数列模型

此动态规划系列主要讲解大约10个系列【后续持续更新】 本篇讲解入门级:斐波那契模型,会在讲解题目同时给出AC代码 为什么叫斐波那契数列模型?因为本篇4道题的状态转移方程都跟斐波那契递推方程差不多,但这点不重要,请往…

Python 全栈体系【四阶】(四)

第四章 机器学习 一、人工智能概述 1. 什么是人工智能 人工智能(Artificial Intelligence)是计算机科学的一个分支学科,主要研究用计算机模拟人的思考方式和行为方式,从而在某些领域代替人进行工作。 2. 人工智能的学科体系 …

Unity-小工具-LookAt

Unity-小工具-LookAt 🥙介绍 🥙介绍 💡通过扩展方法调用 gameObject.LookAtTarget,让物体转向目标位置 💡gameObject.StopLookat 停止更新 💡可以在调用时传入自动停止标记,等转向目标位置后自…

conda环境下ImportError: libmkl_intel_lp64.so.1: cannot open shared object file问题解决

1 问题描述 conda环境下运行模型推理,出现如下错误: (retalking) [rootlocalhost video-retalking]# python inference.py --face examples/face/01.mp4 --audio examples/audio/01.wav --outfile results/01.mp4 Traceback (most recent call last):F…

Fiddler中AutoResponder的简单使用

AutoResponder,自动回复器,用于将 HTTP 请求重定向为指定的返回类型。 这个功能有点像是一个代理转发器,可以将某一请求的响应结果替换成指定的资源,可以是某个页面也可以是某个本地文件 1.使用 打开“Fiddler”,点击…

LeedCode刷题---滑动窗口问题

顾得泉:个人主页 个人专栏:《Linux操作系统》 《C/C》 《LeedCode刷题》 键盘敲烂,年薪百万! 一、长度最小的子数组 题目链接:长度最小的子数组 题目描述 给定一个含有 n 个正整数的数组和一个正整数 target 。…

MySQL执行流程_执行一条select语句,期间发生了什么

文章目录 执行一条select语句,期间发生了什么MySQL执行流程第一步:连接器第二步:查询缓存第三步:解析SQL第四步:执行SQL 执行一条select语句,期间发生了什么 MySQL执行流程 server层负责建立连接、分析和执…

GraphSAGE 到底在训练什么? 图上的Mini-Batch 是怎么训练的 ?

1. 一个端到端的 同构图(Cora数据集)节点分类代码: import argparseimport dgl import dgl.nn as dglnnimport torch import torch.nn as nn import torch.nn.functional as F from dgl import AddSelfLoop from dgl.data import CiteseerGr…

YOLOv8训练好的pt文件如何用来预测

1. 使用原版预测 代码如下: from ultralytics import YOLO# Load a model model YOLO(yolov8n.pt) # load an official model# Predict with the model results model(https://ultralytics.com/images/bus.jpg) # predict on an image命令如下: y…

linux 17day 堡垒机 堡垒机下载 堡垒机安装 堡垒机使用 堡垒机管理服务器 堡垒机管理数据库

目录 堡垒机官网堡垒机下载堡垒机安装堡垒机使用Linux系统上使用web 使用配置站点url配置邮箱创建要管理的服务器创建 特权用户用于管理创建普通用户添加命令过滤命令过滤创建好 之后就需要 给用户名 和管理添加web用户登录 添加数据库mysql 服务区创建用户创建系统用户创建mys…

CRM对小微公司的实际作用:从客户管理到业务拓展

公司作为一个组织,管理方面是重中之重。传统式的人力会是一个较为费时费力的大工程。随着科技的发展,CRM系统完全可以胜任企业管理的工作。那么,CRM有什么特点?对小微公司有哪些作用? 1、提高管理效率 传统的客户管理…

DataFunSummit:2023年数据治理在线峰会-核心PPT资料下载

一、峰会简介 数据治理(Data Governance)是组织中涉及数据使用的一整套管理行为。由企业数据治理部门发起并推行,关于如何制定和实施针对整个企业内部数据的商业应用和技术管理的一系列政策和流程。 数据治理是一个通过一系列信息相关的过程…

MySQL笔记-第09章_子查询

视频链接:【MySQL数据库入门到大牛,mysql安装到优化,百科全书级,全网天花板】 文章目录 第09章_子查询1. 需求分析与问题解决1.1 实际问题1.2 子查询的基本使用1.3 子查询的分类 2. 单行子查询2.1 单行比较操作符2.2 代码示例2.3 …

生化危机5无法启动丢失xlive.dll怎么修复?快速修复教程分享

xlive.dll丢失的5个解决方法与xlive.dll文件丢失原因以及xlive.dll丢失对电脑有什么影响介绍 一、xlive.dll文件丢失原因: 1. 病毒或恶意软件感染:某些病毒或恶意软件会删除或损坏系统文件中的xlive.dll文件,导致其丢失。 2. 误操作&#…

作业12.12

1.闹钟 主函数 #include "widget.h" #include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget) {ui->setupUi(this);t new QTimer(this);idstartTimer(1000);speecher new QTextToSpeech(this); }Widget::~Wid…

QML WebEngineView 全屏和退出

作者: 一去、二三里 个人微信号: iwaleon 微信公众号: 高效程序员 在使用浏览器时,我们经常会用到全屏模式,最常见的场景有:观看视频、阅读文章、在线演示等。全屏模式的优点在于,它可以让用户充分地利用有限的屏幕空间,更好地专注于内容本身,从而提供丰富的沉浸式视觉…

视频剪辑入门:视频批量嵌套合并,成为视频编辑达人

随着数字媒体的快速发展,视频剪辑已经成为一项非常流行的技能。如果对视频剪辑感兴趣,想学习如何将多个视频批量嵌套合并,下面是云炫AI智剪批量嵌套合并视频的一些简单步骤,高效剪辑,成为视频编辑达人不再难。 准备要视…

金融银行软件测试超大型攻略,最受欢迎的金融银行大揭秘附面试题

零、为什么做金融类软件测试 举个栗子,银行里的软件测试工程师。横向跟互联网公司里的测试来说,薪资相对稳定,加班少甚至基本没有,业务稳定。实在是测试类岗位中的香饽饽! 一、什么是金融行业 金融业是指经营金融商…

简单自定义vuex的设计思路

vuex集中式存储管理应用所有组件的状态,并以响应的规则保证状态以可预测的方式 发生变化。 步骤: 1.Store类,保存选项,_mutations,_actions,getters 2.响应式状态:new Vue方式设置响应式。 …

Java网络编程,使用UDP实现TCP(三), 基本实现四次挥手

简介 四次挥手示意图 在四次挥手过程中,第一次挥手中的Seq为本次挥手的ISN, ACK为 上一次挥手的 Seq1,即最后一次数据传输的Seq1。挥手信息由客户端首先发起。 实现步骤: 下面是TCP四次挥手的步骤: 第一次挥手&…