多线程初阶——线程状态

news/2024/7/4 23:00:43

多线程初阶——线程状态

文章目录

  • 多线程初阶——线程状态
    • 1.Thread类及常见构造方法
    • 2.Thread常见的方法
    • 3.线程相关的重要操作
      • 3.1启动线程—start()
      • 3.2中断线程
      • 3.3 等待线程— join()
      • 3.4 获取线程引用
      • 3.5休眠线程—sleep()
    • 4.线程的状态

1.Thread类及常见构造方法

方法说明
Thread()默认无参构造方法
Thread(Runnable target)使用Runnable对象创建线程对象
Thread(String name)创建线程对象,并给线程起名字
Thread(Runnable target,String name)使用Runnable对象创建线程对象,并给线程起名字

给线程起名字

public class demo1 {
    public static void main(String[] args) {
        Thread t = new Thread(() -> {
            while(true){
                System.out.println("Thread");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }

            }
        },"线程一");
        t.start();
        while (true){
            System.out.println("main");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                throw new RuntimeException(e);
            }
        }
    }
}

image-20230129200540985

2.Thread常见的方法

属性方法
IDgetId()
名称getName()
状态getState()
优先级getPriority()
是否后台线程isDaemon()
是否存活isAlive()
是否被中断isInterrupted()

说明

getId()

ID是线程唯一标识,不同线程不会重复

getName()

线程的名称

getState()

表示线程当前所处的一个情况

getPriority()

获得线程的优先级

isDaemon()

JVM会在一个进程的所有非后台线程结束后,才会结束运行,这里的后台,和我们常说的手机后台应用类似线程创建的时候,默认是一个前台线程,前台线程可以阻止进程的退出,后台线程不影响进程的退出

public class Demo5 {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            while (true) {
                System.out.println("thread...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        thread.start();
    }
}

image-20230129214257735

由于线程是前台进程,需要等待运行结束,进程才结束。代码为死循环,所以将会一直执行。

利用setDaemom()方法将线程设置为后台进程,等主线程执行完,进程就结束了,注意:先设置后台进程,再启动线程

public class Demo5 {
    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            while (true) {
                System.out.println("thread...");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
            }
        });
        thread.setDaemon(true);
        thread.start();
        System.out.println("main.....");

    }
}

image-20230129215820274

3.线程相关的重要操作

3.1启动线程—start()

创建Thread对象、重写run方法,只是给线程安排了任务,并没有执行,而调用start方法,才是创建出了线程

3.2中断线程

**线程结束其实就是让线程的入口方法执行完 **

而中断线程,其实就是让线程停止下来,结束入口方法的执行

有2种方法可以中断线程

**方法一:直接用自定义的变量来作为标志位 **

需要给标志位上加volatile关键字

这里我们以李四在银行取钱为例

public class Demo8 {
    private static class MyRunnable implements Runnable {
        public volatile boolean isQuit = false;

        @Override
        public void run() {
            while (!isQuit) {
                System.out.println(Thread.currentThread().getName()
                        + ": 别管我,我忙着转账呢!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName()
                    + ": 啊!险些误了大事");
        }
    }

    public static void main(String[] args) throws InterruptedException {
        MyRunnable target = new MyRunnable();
        Thread thread = new Thread(target, "李四");
        System.out.println(Thread.currentThread().getName()
                + ": 让李四开始转账。");
        thread.start();
        Thread.sleep(5 * 1000);
        System.out.println(Thread.currentThread().getName()
                + ": 老板来电话了,得赶紧通知李四对方是个骗子!");
        target.isQuit = true;
    }
}

image-20230203010328854

方法二:使用Thread自带的标志位

Thread.interrupted()或者Thread.currenThread().isInterrupted()

public class Demo9 {
 private static class MyRunnable implements Runnable {

     @Override
     public void run() {
         while (!Thread.currentThread().isInterrupted()) {
             System.out.println(Thread.currentThread().getName()
                        + ": 别管我,我忙着转账呢!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName()
                    + ": 啊!险些误了大事");
        }

    }

    public static void main(String[] args) throws InterruptedException {
        MyRunnable target = new MyRunnable();
        Thread thread = new Thread(target, "李四");
        System.out.println(Thread.currentThread().getName()
                + ": 让李四开始转账。");
        thread.start();
        Thread.sleep(5 * 1000);
        System.out.println(Thread.currentThread().getName()
                + ": 老板来电话了,得赶紧通知李四对方是个骗子!");
        thread.interrupt();
    }
}

运行结果

image-20230203204711356

这时抛出了InterruptedException异常

这是为什么呢?

由于线程的有效任务是打印一句话,这个操作耗时比较小,大部分时间线程都在sleep状态,正常来说,当线程在运行真正有效任务时去中断才是一个有效的中断,而在线程休眠的时候中断,其实是把休眠给中断了,而休眠本身没有到指定的时间,所以抛出了InterruptedException异常

当我们去掉线程中的休眠时,结果如下

image-20230203220249387

这时候线程才真正的中断了

3.3 等待线程— join()

我们知道线程之间的执行顺序是根据系统调度随机执行的,但有时我们需要等待一个线程执行完,再执行下一个线程,这时我们需要一个方法明确等待线程结束

public class Demo10 {
    public static void main(String[] args) throws InterruptedException {
        Runnable target = () -> {
            for (int i = 0; i < 3; i++) {
                System.out.println(Thread.currentThread().getName() + ":正在工作!");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(Thread.currentThread().getName() + "结束了工作");
        };
        Thread thread1 = new Thread(target, "李四");
        Thread thread2 = new Thread(target, "王五");
        System.out.println("李四先工作");
        thread1.start();
        thread1.join();
        System.out.println("李四结束了工作,王五开始工作");
        thread2.start();
        thread2.join();
        System.out.println("王五结束了工作");
    }
}

image-20230203221145829

join()其他方法

public void join()等待线程结束(一直等,知道线程执行的任务结束)
public void join(long millis)等待线程结束,但等待millis毫秒
public void join(long millis, int nanos)同理

3.4 获取线程引用

private static Thread currentThread()

返回当前线程对象的引用

3.5休眠线程—sleep()

让线程休眠休眠一会

图解sleep()的具体使用

image-20230204002702109

4.线程的状态

在Java线程分为6种状态

1. NEW:创建好了一个Java的Thread对象,并安排好了任务,没有调用start()方法之前,和PCB没有关系

2. RUNNABLE:运行+就绪状态,在执行任务时的一个常态之一

3. TIMED_WAITING:指定了一个时间的阻塞队列,过时不候

4. WAITING :没有指定时间的等待,一直死等

5. BLOCK:等待锁的状态

6. TERMINATED :结束,完成状态,PCB已经被销毁了,但是Java对象还在

查看线程状态

public class Demo14 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread=new Thread(()->{
            for (int i = 0; i < 5; i++) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        System.out.println("线程创建之前:"+thread.getState());
        thread.start();
        Thread.sleep(1000);
        System.out.println("启动线程,创建好PCB后:"+thread.getState());
        thread.join();
        System.out.println("线程执行完成后:"+thread.getState());
    }
}

image-20230204004138603

线程之间相互转换

image-20230204004728035
觉得不错就留下你的三连吧


http://lihuaxi.xjx100.cn/news/804004.html

相关文章

[项目管理] 关于测试与测试设备的一些想法

文章目录QA如何跨岗测试需要做适当的初步分析系统警告信息是分析问题的原点&#xff0c;如果有警告从开发者角度感悟测试关于测试环境问题的一个讨论云化之后测试设备的管理QA如何跨岗 2019年SAFEe培训时&#xff0c;问一个系统测试同事&#xff0c;现在都不写用例了&#xff…

C/C++之fopen

前言 在我们需求开发中&#xff0c;经常需要读取文件的内容&#xff0c;在C中&#xff0c;通常使用open/close或者fopen/fclose来完成这个功能&#xff0c;那么open与fopen有什么异同呢&#xff0c;在开发中我们应当如何选择这两个函数呢&#xff0c;我们一起来看一下。 1.fop…

图解LeetCode——1145. 二叉树着色游戏(难道:中等)

一、题目 有两位极客玩家参与了一场「二叉树着色」的游戏。游戏中&#xff0c;给出二叉树的根节点 root&#xff0c;树上总共有 n 个节点&#xff0c;且 n 为奇数&#xff0c;其中每个节点上的值从 1 到 n 各不相同。 最开始时&#xff1a; 「一号」玩家从 [1, n] 中取一个值…

软件测试基础(五) 之 了解测试团队的组织架构

今天来了解一下软件测试团队的组织架构模式到底是什么样子。测试团队的组织架构模式的分类一个公司软件测试的组织架构&#xff0c;可能会决定你未来的成长空间&#xff0c;同时也决定了我们的工作模式到底是什么样子。现在测试行业内通常测试团队的组织架构主要分成两种&#…

Exynos 4412 看门狗定时器中断

如果想弄懂看门狗定时器中断&#xff0c;要掌握下面两个知识点&#xff1a; 1 懂寄存器 Cortex A9采用的是ARM官方规定的中断处理机制 有两大类寄存器决定了中断工作状态 1) exynos 4412 特有的寄存器(在第26章) 2) Cortex A9 规定的工作寄存器(在第9章和第10章) 2 懂中断处理过…

前端面试套题系列(第二篇)

1、HTML 语义化标签 语义化标签,旨在让标签有自己的含义,优势是: (1) 使得在没有 CSS 的情况下,页面也能呈现出很好的内容结构、代码结构 (2) 有利于 SEO:和搜索引擎建立良好沟通,有助于爬虫抓取更多的有效信息 (3) 方便其他设备(比如盲人阅读器来解析)来解析 HT…

【信管11.1】项目采购相关知识及过程

项目采购相关知识及过程项目采购管理过程做为十大知识领域的最后一部分内容&#xff0c;含金量也是不容忽视的。在这一大章节中&#xff0c;除了普通的采购管理过程之外&#xff0c;我们还要学习采购相关的一些法规知识、合同相关知识等。总之&#xff0c;内容不少&#xff0c;…

【Python学习笔记】12. 字符串

前言 字符串是 Python 中最常用的数据类型。我们可以使用引号( ’ 或 " )来创建字符串。 Python3 字符串 字符串是 Python 中最常用的数据类型。我们可以使用引号( ’ 或 " )来创建字符串。 创建字符串很简单&#xff0c;只要为变量分配一个值即可。例如&#xf…