线程-Thread类及常见方法

目录

一、创建线程

1.继承 Thread 类

2. 实现 Runnable 接口

 3.匿名内部类创建 Thread 子类对象

4. 匿名内部类创建 Runnable 子类对象

5. lambda 表达式创建 Runnable 子类对象

二、Thread 类及常见方法 

2.1 Thread 的常见构造方法

 2.2 Thread 的几个常见属性

2.3 启动一个线程-start()

2.4 中断一个线程  

2.5 等待一个线程-join()

三. 线程的状态


若想了解线程的基本概念,请参照另一篇博文 :进程和线程 

一、创建线程

1.继承 Thread

1) 继承 Thread 来创建一个线程类 .
class MyThread extends Thread {@Overridepublic void run() {System.out.println("这里是线程运行的代码");}
}

 2) 创建 MyThread 类的实例

Thread t = new MyThread();

 3) 调用 start 方法启动线程

t.start(); // 线程开始运行

2. 实现 Runnable 接口

1)通过 类 实现 Runnable 接口,重写run方法,Runnable 接口表示一个“可执行的任务”,交给线程来使用。
class MyRunnable implements Runnable {@Overridepublic void run() {System.out.println("这里是线程运行的代码");}
}

 2) 创建 Thread 类实例, 调用 Thread 的构造方法时将 Runnable 对象作为 target 参数.

 Thread t = new Thread(new MyRunnable());
//或者Runnable runnable = new MyRunnable();Thread t = new Thread(runnable);

 3) 调用 start 方法

t.start(); // 线程开始运行

对比上面两种方法:

  • 继承 Thread , 直接使用 this 就表示当前线程对象的引用.
  • 实现 Runnable 接口, this 表示的是 MyRunnable 的引用. 需要使用 Thread.currentThread(),当前线程实例对象。

 3.匿名内部类创建 Thread 子类对象

            在创建Thread类的对象时使用匿名内部类,并重写方法。

    public static void main(String[] args) {Thread t = new Thread() {@Overridepublic void run() {while (true) {System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}};t.start();
}

4. 匿名内部类创建 Runnable 子类对象

public static void main(String[] args) {   Thread t = new Thread(new Runnable() {@Overridepublic void run() {while (true) {System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}});t.start();
}

5. lambda 表达式创建 Runnable 子类对象

        该方法是最简便创建线程的方法, lambda 表达式本质上是一个函数式接口(一个接口中只有一个抽象方法),自身就是run方法,表示逻辑。   

         lambda 表达式可以理解为:匿名内部类的简化,实际上为创建了一个类,实现接口,并重写方法。

//eg:  (函数式接口参数)-> 表达式 / {代码块};public static void main(String[] args) {Thread t = new Thread(() -> {while (true) {System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t.start();
}

二、Thread 类及常见方法 

        Thread 类是 JVM 用来管理线程的一个类,换句话说,每个线程都有一个唯一的 Thread 对象与之关联。

        Thread 类的对象就是用来描述一个线程执行流的,JVM 会将这些 Thread 对象组织起来,用于线程调度,线程管理。

                         

2.1 Thread 的常见构造方法

Thread t1 = new Thread();
Thread t2 = new Thread(new MyRunnable());
Thread t3 = new Thread("这是我的名字");
Thread t4 = new Thread(new MyRunnable(), "这是我的名字");

 2.2 Thread 的几个常见属性

  1. getId() ,ID 是线程的唯一标识,不同线程不会重复
  2. getName(),名称是各种调试工具用到
  3. getState(),状态表示线程当前所处的一个情况,下面我们会进一步说明
  4. getPriority(),优先级高的线程理论上来说更容易被调度到
  5. isDaemon() 关于后台线程,需要记住一点:JVM会在一个进程的所有非后台线程结束后,才会结束运行。
  6. isAlive() ,是否存活,即简单的理解,为 run 方法是否运行结束了
  7. isInterrupted() ,线程中断。

 Thread.currentThread(),返回当前线程实例对象。

public class ThreadDemo {public static void main(String[] args) {Thread thread = new Thread(() -> {for (int i = 0; i < 10; i++) {try {System.out.println(Thread.currentThread().getName() + ": 我还
活着");Thread.sleep(1 * 1000);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println(Thread.currentThread().getName() + ": 我即将死去");});System.out.println(Thread.currentThread().getName() + ": ID: " + thread.getId());System.out.println(Thread.currentThread().getName() + ": 名称: " + thread.getName());System.out.println(Thread.currentThread().getName() + ": 状态: " + thread.getState());System.out.println(Thread.currentThread().getName() + ": 优先级: " + thread.getPriority());System.out.println(Thread.currentThread().getName() + ": 后台线程: " + thread.isDaemon());System.out.println(Thread.currentThread().getName() + ": 活着: " + thread.isAlive());System.out.println(Thread.currentThread().getName() + ": 被中断: " + thread.isInterrupted());thread.start();while (thread.isAlive()) {}System.out.println(Thread.currentThread().getName() + ": 状态: " + thread.getState());}
}

2.3 启动一个线程-start()

          之前我们已经看到了如何通过覆写 run 方法创建一个线程对象,但线程对象被创建出来并不意味着线程就开始运行了。

        start()内部是会调用到系统api,在系统内核中创建线程

        run(),单纯描述了该线程要执行什么工作。

        本质区别 在于是否在系统内核中创建了一个线程。

2.4 中断一个线程  

        interrupt中断,让一个线程停止运行run方法,

目前常见的有以下两种方式:

  • 通过共享的标记来进行沟通,手动设置标志位。
  • 调用 interrupt() 方法来通知,Thread 内部包含了一个 boolean 类型的变量作为线程是否被中断的标记.使用 Thread.interrupted() 或者 Thread.currentThread().isInterrupted() 代替自定义标志位。

thread 收到通知的方式有两种:
1. 如果线程因为调用 wait/join/sleep 等方法而阻塞挂起,则以 InterruptedException 异常的形式通知,清除中断标志

  • 当出现 InterruptedException 的时候, 要不要结束线程取决于 catch 中代码的写法. 可以选择忽略这个异常, 也可以跳出循环结束线程.
2. 否则,只是内部的一个中断标志被设置, thread 可以通过
  • Thread.interrupted() 判断当前线程的中断标志被设置,清除中断标志
  • Thread.currentThread().isInterrupted() 判断指定线程的中断标志被设置,不清除中断标志
这种方式通知收到的更及时,即使线程正在 sleep 也可以马上收到。

        如下代码就是第一种 因为调用 wait/join/sleep 等方法而阻塞挂起,则以 InterruptedException 异常的形式通知,清除中断标志,所以线程run并没有结束,可以抛出异常break解决。

package thread;// 线程终止
public class Demo9 {public static void main(String[] args) {Thread t = new Thread(() -> {// Thread 类内部, 有一个现成的标志位, 可以用来判定当前的循环是否要结束.while (!Thread.currentThread().isInterrupted()) {System.out.println("线程工作中");try {Thread.sleep(1000);} catch (InterruptedException e) {// 1. 假装没听见, 循环继续正常执行.e.printStackTrace();// 2. 加上一个 break, 表示让线程立即结束.// break;// 3. 做一些其他工作, 完成之后再结束.// 其他工作的代码放到这里.break;}}});t.start();try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("让 t 线程终止. ");t.interrupt();}
}

2.5 等待一个线程-join()

        有时,我们需要等待一个线程完成它的工作后,才能进行自己的下一步工作。这时我们需要一个方法明确等待线程的结束。        

         主线程中,调用t.join() => 主线程等待 t 线程先结束。

. 线程的状态

        线程的状态是一个枚举类型 Thread.State

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

  • NEW: 安排了工作, 还未开始行动
  • RUNNABLE: 可工作的. 又可以分成正在工作中和即将开始工作.
  • BLOCKED: 这几个都表示排队等着其他事情
  • WAITING: 这几个都表示排队等着其他事情
  • TIMED_WAITING: 这几个都表示排队等着其他事情
  • TERMINATED: 工作完成了.
//示例
package thread;public class Demo12 {public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {while (true) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});// 在调用 start 之前获取状态, 此时就是 NEW 状态System.out.println(t.getState());t.start();for (int i = 0; i < 5; i++) {System.out.println(t.getState());Thread.sleep(1000);}t.join();// 在线程执行结束之后, 获取线程的状态, 此时是 TERMINATED 状态System.out.println(t.getState());}
}

 结语:Thread类及常见方法的相关分享到这里就结束了,希望对大家的学习会有帮助,如果大家有什么问题或者不同的见解,欢迎大家评论区的留言, 感谢支持 !!!

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C++类与对象(5)—流运算符重载、const、取地址

目录 一、流输出 1、实现单个输出 2、实现连续输出 二、流输入 总结&#xff1a; 三、const修饰 四、取地址 .取地址及const取地址操作符重载 五、[ ]运算符重载 一、流输出 1、实现单个输出 创建一个日期类。 class Date { public:Date(int year 1, int month 1,…

JVM内存模型及调优

本文将为大家详细介绍JVM内存模型及如何对JVM内存进行调优。我们将分为以下几个部分进行讲解&#xff1a; JVM内存模型概述JVM内存区域及作用JVM内存调优方法实战案例与优化技巧 一、JVM内存模型概述 在深入了解JVM内存模型之前&#xff0c;我们需要先了解一下Java内存模型&am…

ELK企业级日志分析平台——logstash

部署 新建一台虚拟机elk4部署logstash [rootelk4 ~]# yum install -y jdk-11.0.15_linux-x64_bin.rpm[rootelk4 ~]# yum install -y logstash-7.6.1.rpm 命令方式 [rootelk4 bin]# /usr/share/logstash/bin/logstash -e input { stdin { } } output { stdout {} } elasticsearc…

webpack plugin

1、基本写法及使用 这里用到 emit 钩子 及make 钩子&#xff0c;前者是串行后者是并行 /*** 1.webpack加载webpack.config.js中所有配置&#xff0c;此时就会new TestPlugin()&#xff0c;执行插件的constructor2.webpack创建compiler对象3.遍历所有plugins中插件&#xff0…

中国信息通信研究院发布《全球数字治理白皮书》调”转变

加gzh“大数据食铁兽”&#xff0c;回复“20231123”&#xff0c;获取材料完整版 导读 中国信息通信研究院连续第三年发布《全球数字治理白皮书》本年度报告在延续以往对全球数字治理核心议题和重要机制进展评估展望的基础上&#xff0c;首次尝试提出全球数字治理的定义和体…

“继续教育”招生报名网存在支付漏洞

1.找到该网站的一个登录页面&#xff0c;注册好账户密码登录进去 2&#xff0c;进去之后&#xff0c;找到一个网上缴费功能 3.选择338元的套餐&#xff0c;支付方式我选的支付宝用burp抓包 发现money0参数与金额有关&#xff0c;于是就尝试把monet0改成一看看能不能搞一个零元购…

IO多路转接之epoll

目录 一. epoll的实现原理 二. epoll的相关接口 2.1 epoll_create -- 创建epoll模型 2.2 epoll_ctl -- 对epoll模型进行控制 2.3 epoll_wait -- 等待epoll所关注的事件就绪 2.4 epoll相关接口的使用方法 三. Epoll服务器的模拟实现 3.1 EpollServer类的声明 3.2 Epoll…

系统安全测试要怎么做?

进行系统安全测试时&#xff0c;可以按照以下详细的步骤进行&#xff1a; 1、信息收集和分析&#xff1a; 收集系统的相关信息&#xff0c;包括架构、部署环境、使用的框架和技术等。 分析系统的安全需求、威胁模型和安全策略等文档。 2、威胁建模和风险评估&#xff1a; …

SpringBoot3核心原理

SpringBoot3核心原理 事件和监听器 生命周期监听 场景&#xff1a;监听应用的生命周期 可以通过下面步骤自定义SpringApplicationRunListener来监听事件。 ①、编写SpringApplicationRunListener实现类 ②、在META-INF/spring.factories中配置org.springframework.boot.Sprin…

【Apache Doris】一键实现万表MySQL整库同步 | 快速体验

【Apache Doris】一键实现万表MySQL整库同步 | 快速体验&#xff09; 一、 环境信息1.1 硬件信息1.2 软件信息 二、 流程介绍三、 前提概要3.1 安装部署3.2 JAR包准备3.2.1 数据源3.2.2 目标源 3.3 脚本模版 四、快速体验五、常见问题5.1 Mysql通信异常5.2 MySQL无Key同步异常5…

7.5 Windows驱动开发:监控Register注册表回调

在笔者前一篇文章《内核枚举Registry注册表回调》中实现了对注册表的枚举&#xff0c;本章将实现对注册表的监控&#xff0c;不同于32位系统在64位系统中&#xff0c;微软为我们提供了两个针对注册表的专用内核监控函数&#xff0c;通过这两个函数可以在不劫持内核API的前提下实…

爱心发射代码带名字升级版

上次的爱心发射发出来之后&#xff0c;群友想问能不能把心爱的人名字放在爱心中间。 当然没问题啊&#xff0c;于是我就改了改代码&#xff0c;让女神王铁蛋显示在爱心中间&#xff0c;同时还可以在屏幕上飘动满屏的王铁蛋&#xff0c;大大小小、快快慢慢的王铁蛋。 这还拿不下…