线程的常用方法及六种状态

news2024/11/28 10:35:25

一、线程核心执行流程方法 -- run()

        run方法是Runnable接口中定义的。所有实现Runnable的接口的子类都需要覆写run方法。

        run方法是线程的核心执行流程方法,也就是说,run方法决定了线程启动后要干什么,当run方法执行完毕(JVM启动run方法),线程会进入销毁状态。

二、启动线程-- start()

        start方法是Thread类定义的。start方法是启动线程调用的方法,只有当线程对象调用start方法之后才会被系统调度,进入运行状态。

        当线程启动之后,若再次调用start()方法,就会抛出IllegalThreadStateException(非法线程状态异常),说明该线程已经启动过了。

三、中断线程

        (一)通过共享变量中断线程

public class ThreadInterruptByVariable {
    private static class MyThread implements Runnable{
        volatile boolean isQuit = false;
        @Override
        public void run() {
            while (!isQuit){
                System.out.println(Thread.currentThread().getName() + "  别烦我,正在转账呢~~");
                try {
                    // 每次转账休眠1s
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName()+"被中断了");
        }
    }
    public static void main(String[] args) throws InterruptedException {
        MyThread mt = new MyThread();
        Thread thread = new Thread(mt,"小A线程");
        System.out.println("小A可以开始转账了~");
        thread.start();
        // 主线程休眠3秒
        Thread.sleep(3000);
        System.out.println("钱转完了,让小A停止!");
        mt.isQuit = true;
    }
}

        (二)使用Thread.interrupted()(静态方法)或Thread对象的(成员方法)isInterrupted()

public class ThreadInterruptByMethod {
    private static class MyThread implements Runnable{
        @Override
        public void run() {
// 1. 静态方法,判断当前线程是否被中断了
//            while (Thread.interrupted()){
//2.成员方法,判断当前线程是否被中断了
            while (Thread.currentThread().isInterrupted()){
                System.out.println(Thread.currentThread().getName() + "  别烦我,正在转账呢~~");
                try {
                    // 每次转账休眠1s
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    System.out.println("转账中断");
                    // 当线程被中断时,会抛出中断异常
                    // 抛出中断异常之后,中断状态就会还原!--》因为线程调用了sleep方法
                    break;
                }
            }
            System.out.println(Thread.currentThread().getName()+"被中断了");
        }
    }
    public static void main(String[] args) throws InterruptedException {
        MyThread mt = new MyThread();
        Thread thread = new Thread(mt,"小A线程");
        System.out.println("小A可以开始转账了~");
        thread.start();
        // 主线程休眠3秒
        Thread.sleep(3000);
        System.out.println("钱转完了,让小A停止!");
        // 中断子线程
        // 调用此方法就会将子线程的状态置为中断状态
        thread.interrupted();
    }
}

thread 收到通知的方式有两种:

1. 如果线程因为调用 wait/join/sleep 等方法而阻塞挂起,则以 InterruptedException 异常的形式通 知,清除中断标志(无论是使用Thread.interrupted() 还是使用Thread.currentThread().isInterrupted(),状态都会从TRUE 重新置为 FALSE

        当出现 InterruptedException 的时候, 要不要结束线程取决于 catch 中代码的写法. 可以选择 忽略这个异常, 也可以跳出循环结束线程.

2.线程没有调用以上方法,处在正常运行状态时收到中断通知thread.interrupt()

Thread.interrupted()判断当前线程是否被中断,若中断状态为true 清除中断标志 TRUE -->FALSE

Thread.currentThread.isInterrupted(); 判断指定线程对象是否状态为中断状态,若状态为true,不会清除中断标志。TRUE-->TRUE

四、等待线程--join()

join方法---Thread类中定义的成员方法。 

线程对象. join():在哪个线程(A)中调用别的线程对象的join方法(B线程对象.join()),意思就是A线程要等待B线程执行完毕后再继续执行本线程的后续代码。

Eg:若在主线程中调用thread1.join(),主线程就会进入阻塞状态,直到thread1执行结束,主线程才会继续向后执行

public class ThreadJoin {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + "还在学习JavaSE阶段...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        },"JavaSE线程");
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                System.out.println(Thread.currentThread().getName() + "进入数据结构的学习部分");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        },"数据结构线程");
        System.out.println("先学习JavaSE");
        t1.start();
        // 主线程死等t1,直到t1执行结束主线程再恢复执行
        t1.join();
        // 此时走到这里,t1线程已经执行结束,再启动t2线程
        t2.start();
        // 在哪调用别的线程的join方法,阻塞的是调用join的线程
        // main -> 调用t2.join() 阻塞主线程,直到t2完全执行结束再恢复主线程的执行
        // 主线程只等t2 2000ms - 2s,若t2在2s之内还没结束,主线程就会恢复执行
        t2.join(2000);
        // t2线程也执行结束了,继续执行主线程
        System.out.println("开始学习JavaEE");
        System.out.println(Thread.currentThread().getName());
    }
}

五、休眠线程--sleep()

sleep():Thread类的静态方法,在哪个线程中调用,就休眠哪个线程

调用sleep方法的线程会让出CPU资源,从运行状态转为就绪状态,等待CPU继续调度。

六、 yeild()

线程调用yeild()  ==》会从运行状态转为就绪状态!

调用yeild 方法的线程也会主动让出CPU资源,从运行状态转为就绪状态,等待CPU继续调度。

到底什么时候让出CPU ,什么时候又重新被CPU再次调度,都是操作系统OS调度的,我们无权选择

可能会出现以下情况:

  1. 让出后立马又被调度了
  2. 让出之后,很久都不调度

七、wait() 和 notify()

    线程间的等待与唤醒机制。wait()和 notify()是Object类的方法,用于线程的等待与唤醒,必须搭配synchronized锁来使用。

(一)等待方法

死等,线程进入waiting状态,直到有其他线程调用notify()将其唤醒

 等待一段时间,进入timed_waiting状态。若在该时间段内线程被唤醒,则继续执行,若超过相应时间还没有其它线程唤醒此线程,此线程也不再等待,恢复执行。

(二)唤醒方法

随机唤醒一个正处于等待状态的线程 

唤醒所有处于等待状态的线程 

(三)代码示例

        调用wait方法的前提是首先要获取到该对象的锁(synchronized对象锁),调用wait方法会释放锁,该线程进入等待队列等待被唤醒,被唤醒后不是立即恢复执行,而是进入阻塞状态,竞争锁。

public class WaitAndNotify {
    private static class WaitTask implements Runnable {
        private Object lock;
        public WaitTask(Object lock) {
            this.lock = lock;
        }
        @Override
        public void run() {
            synchronized (lock) {
                System.out.println(Thread.currentThread().getName() + "准备进入等待状态");
                // 此线程在等待lock对象的notify方法唤醒
                try {
//调用 wait()的线程会进入waiting状态,等待被其他线程唤醒(lock.notify())
                    lock.wait();
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
//被唤醒结束后,线程从wait()之后开始继续执行
                System.out.println(Thread.currentThread().getName() + "等待结束,本线程继续执行");
            }
        }
    }
    private static class NotifyTask implements Runnable {
        private Object lock;
        public NotifyTask(Object lock) {
            this.lock = lock;
        }
        @Override
        public void run() {
            synchronized (lock) {
                System.out.println("准备唤醒");
                // 随机唤醒一个处在lock对象上等待的线程
//                lock.notify();
                  lock.notifyAll();
                System.out.println("唤醒结束");
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Object lock = new Object();
        // 创建三个等待线程
        Thread t1 = new Thread(new WaitTask(lock),"t1");
        Thread t2 = new Thread(new WaitTask(lock),"t2");
        Thread t3 = new Thread(new WaitTask(lock),"t3");
        // 创建一个唤醒线程
        Thread notify = new Thread(new NotifyTask(lock),"notify线程");
        t1.start();
        t2.start();
        t3.start();
        Thread.sleep(100);
        notify.start();
    }
}

 

()非法监视器状态异常

如果调用wait()和notify()没有获取锁[没有搭配synchronized锁来使用],就会排除非法的监视器状态异常

八、线程的六种状态 

public class ThreadState {
    public static void main(String[] args) {
        for (Thread.State state:Thread.State.values()) {
            System.out.println(state);
        }
    }
}

  1. new :新建线程对象就是new状态
  2. Runnable : 新建状态的下一个状态,可执行状态(真正在运行的(Running)和即将开始执行的(Ready),都是这个状态)
  3. Blocked:锁等待,需要等待其他线程对象释放锁对象
  4. WAITTING:等待被另一个线程唤醒(notify方法)
  5. TIMED_WAITTING: 超时等待,需要等待一段时间后自动唤醒

 3,4,5 都是等待状态,都属于线程的阻塞状态(该线程需要暂缓执行,这三个造成暂缓执行的原因不同),当前线程暂停执行,等待其他任务或者资源

      6.Terminated: 终止状态,表示当前线程已经执行结束了,可以被销毁

线程的run方法执行完毕后,或者抛出异常不正常执行完毕都会进入终止状态。

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

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

相关文章

2.11 PE结构:添加新的节区

在可执行PE文件中&#xff0c;节&#xff08;section&#xff09;是文件的组成部分之一&#xff0c;用于存储特定类型的数据。每个节都具有特定的作用和属性&#xff0c;通常来说一个正常的程序在被编译器创建后会生成一些固定的节&#xff0c;通过将数据组织在不同的节中&…

微信小程序接入隐私弹窗说明及详细过程

相信各位做小程序的小伙伴在微信小程序后台应该都接到了官方通知的小程序隐私新规&#xff0c;如果还未收到的小程序可以看一下&#xff1a; 为规范开发者的用户个人信息处理行为&#xff0c;保障用户合法权益&#xff0c;自2023年9月15日起&#xff0c;对于涉及处理用户个人信…

OpenCV 09(形态学)

一、形态学 形态学指一系列处理图像 形状特征 的图像处理技术. 形态学的基本思想是利用一种特殊的结构元(本质上就是卷积核)来测量或提取输入图像中相应的形状或特征&#xff0c;以便进一步进行图像分析和目标识别。这些处理方法基本是对二进制图像进行处理, 即黑白图像卷积核…

JUC编程中锁引发的“见解”

JUC编程中锁引发的“见解” 一大早就在想锁是干嘛的&#xff1f;什么情况下要用锁&#xff1f;想了很多&#xff0c;下面的所有表述都是就是我的思考流程&#xff0c;欢迎所有人一起讨论、更正。 文章目录 JUC编程中锁引发的“见解”1、什么是JUC编程?2、JUC编程中什么情况下需…

C/C++之链表的建立

个人主页&#xff1a;点我进入主页 专栏分类&#xff1a;C语言初阶 C语言程序设计————KTV C语言小游戏 C语言进阶 C语言刷题 欢迎大家点赞&#xff0c;评论&#xff0c;收藏。 一起努力&#xff0c;一起奔赴大厂。 目录 1.头插 1.1简介 1.2代码实现头插 …

二维数组前缀和(JAVA)

力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 暴力 双层for循环&#xff0c;遍历子矩阵。 前缀和算法&#xff1a; class NumMatrix {private int sum[][];private int matrix[][];public NumMatrix(int[][] matrix) {this.matrixmatrix;int row…

AI 帮我写代码——Amazon CodeWhisperer 初体验

文章作者&#xff1a;游凯超 人工智能的突破和变革正在深刻地改变我们的生活。从智能手机到自动驾驶汽车&#xff0c;AI 的应用已经深入到我们生活的方方面面。而在编程领域&#xff0c;AI 的崭新尝试正在开启一场革命。Amazon CodeWhisperer&#xff0c;作为亚马逊云科技的一款…

【高德地图】 覆盖物/画点/画折线/画多边形/画矩形/画圆

官方示例 https://lbs.amap.com/demo/javascript-api/example/mouse-operate-map/mouse-draw-overlayers <!doctype html> <html lang"en"><head><meta charset"utf-8"><meta http-equiv"X-UA-Compatible" content…

07_瑞萨GUI(LVGL)移植实战教程之LVGL对接EC11旋转编码器驱动

本系列教程配套出有视频教程&#xff0c;观看地址&#xff1a;https://www.bilibili.com/video/BV1gV4y1e7Sg 7. LVGL对接EC11旋转编码器驱动 本次实验我们向LVGL库中对接EC11旋转编码器驱动&#xff0c;让我们能通过EC11旋转编码器操作UI。 7.1 复制工程 上次实验得出的工…

一文读懂Swin-Transformer

系列文章目录 记录CV领域大模型的学习历程&#xff0c;欢迎大家一起讨论&#xff0c;互相学习。 ViT,DETR(一),DETR(二)DETR(三) 文章目录 系列文章目录前言一、整体框架1.Patch Embedding2.Patch Merging3.Swin Transformer Block3.1 Window Partition/Reverse3.2 Window-MSA…

C#__文件操作之FileInfo和DirectoryInfo

// 代码&#xff08;含注释&#xff09; class Program{static void Main(string[] args){// FileInfo 文件操作FileInfo myFile new FileInfo("D:\C#编程\文件操作之FileInfo和DirectoryInfo\TextFile1.txt");// 实例方法// myFile.CopyTo("D:\C#编程\文件操作…

空中跳一跳

欢迎来到程序小院 空中跳一跳 玩法&#xff1a; 跳一跳长按鼠标左键&#xff0c;松开鼠标进行跳跃&#xff0c;跳到下一个格子中&#xff0c;进行分数统计&#xff0c;三次生命机会&#xff0c;格子中也会有爱心出现&#xff0c;吃掉安心增加一次生命哦^^。开始游戏https://ww…

第19章 并发与竞争实验(iTOP-RK3568开发板驱动开发指南 )

在前面章节的学习中&#xff0c;相信大家已经对用户空间与内核空间数据传递进行了实验&#xff0c;假如要传递的数据被存放在了全局变量&#xff0c;该数据就可以作为共享资源被多个任务共同读写&#xff0c;从而造成数据的错误传输&#xff0c;多个程序同时访问一个共享资源产…

取个好名,是一生中极为重要之事

我们每十年一大运&#xff0c;五年一小运。每交次大运时&#xff0c;就会改变一次你身边的一切环境。每个大运&#xff0c;都会把你带入不同的风景&#xff0c;人生想要须尽欢&#xff0c;就不要太在意外在的一切&#xff0c;永远向内求。有志同道合的人就一起上路&#xff0c;…

《Tree of Thoughts: Deliberate Problem Solving with Large Language Models》中文翻译

《Tree of Thoughts: Deliberate Problem Solving with Large Language Models》- 思维树&#xff1a;用大型语言模型有意识地解决问题 论文信息摘要1. 介绍2. 背景3. 思想树&#xff1a;用 LM 有意识地解决问题4. 实验4.1 24 人游戏4.2 创意写作4.3 迷你填字游戏 5. 相关工作6…

语音芯片NRK3302 在按摩仪上的应用

在当今生活节奏快&#xff0c;生活压力大的现代社会。按摩仪已逐渐成为人们生活中不可或缺的日常用品&#xff0c;人们需要一个能够随时放松身体的工具。智能按摩仪应运而生&#xff0c;在按摩仪中加入语音芯片&#xff0c;让按摩仪变得更加智能&#xff0c;使用起来更加便利化…

私有云不是真正的云计算!

大数据产业创新服务媒体 ——聚焦数据 改变商业 中国云计算遇到困境&#xff0c;IaaS层面&#xff0c;阿里云、腾讯云等增长乏力&#xff1b;SaaS没有发展起来。反观美国&#xff0c;整个云计算蓬勃发展&#xff0c;AWS、微软云、谷歌云体量更大&#xff0c;增速却不低&#x…

YOLO目标检测——工地安全帽识别检测数据集+已标注yolo格式标签下载分享

实际项目应用&#xff1a;目标检测工地安全帽识别检测数据集在工地安全监测、工地管理、安全培训和教育、违规检测和预警以及安全统计和分析等领域都有着广泛的应用。通过准确识别和检测工人是否佩戴安全帽&#xff0c;可以帮助提高工地的安全性和管理效率&#xff0c;减少事故…

通过finalshell快速在ubuntu上安装jdk1.8

这篇文章主要介绍一下怎么通过finalshell连接ubuntu&#xff0c;然后在ubuntu上安装jdk1.8&#xff0c;让不熟悉linux操作系统的童鞋也能快速地完成安装。 目录 一、准备一台虚拟机 二、安装finalshell远程连接工具 三、获取ubuntu虚拟机的ip地址 四、通过finalshell连接u…

Spring以及SpringBoot/SpringCloud注解

一、SpringBoot/Spring 1、SpringBootApplication 包含Configuration、EnableAutoConfiguration、ComponentScan通常在主类上 其中ComponentScan让Spring Boot扫描到Configuration类并把它加入到程序上下文&#xff0c;如果扫描到有Component Controller Service等这些注解的…