当前位置: 首页 > news >正文

【Java 并发编程】线程的基本使用(持续更新优化)

目录

一、Thread

1.1 构造方法

1.2 核心属性

二、线程的操作方法

2.1 启动线程

2.2 线程中断机制

2.2.1 线程中断机制

2.2.2 中断线程的常见方式

2.2.2.1 使用自定义的标志位结合 volatile 实现

2.2.2.2 通过 AtomiucBoolean 进行中断

2.2.2.3 interrupted

2.2.2.4 isInterrupted

2.2.4 线程中断的注意事项

2.3 线程等待

2.4 获取当前线程引用

2.5 线程休眠暂停执行

2.6 线程让步

三、线程的进阶使用方式

3.1 线程中断 LockSupport

3.1.1 线程等待和唤醒的方法

3.1.2 Object的线程等待唤醒机制

3.1.3 Condition的线程等待唤醒机制

3.1.4 LockSupport 的线程阻塞和唤醒

3.1.5 LockSupport 方法介绍


一、Thread

Thread 类是 JVM 用来管理线程的一个类,换句话说,每个线程都有一个唯一的 Thread 对象与之关联。Thread 类的对象就是用来描述一个线程执行流的,JVM 会将这些 Thread 对象组织起来,用于线程调度,线程管理。

1.1 构造方法

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

 name参数,是给线程起了一个名字。这里的名字,不影响程序执行,只是方便咱们在调试的时候,快速找到咱们关心的线程。

1.2 核心属性

  • ID 是线程的唯一标识,不同线程不会重复
  • 名称是各种调试工具用到
  • 状态表示线程当前所处的一个情况,下面我们会进一步说明
  • 优先级高的线程理论上来说更容易被调度到
  • 关于后台线程,需要记住一点:JVM会在一个进程的所有非后台线程结束后,才会结束运行。也就是说前台线程会阻止java进程结束,后台进程不会阻止进程的结束。创建的线程默认是前台的,可以通过setDaemon设置为后台的。
  • 是否存活,即简单的理解,为 run 方法是否运行结束了
  • 线程的中断问题,下面我们进一步说明
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.1 启动线程

在系统中真正创建出线程需要如下步骤,而系统 API start 方法会在系统内核将对应任务进行创建:

  1. 创建 PCB 进程管理块
  1. 把 PCB 加入到对应链表

启动线程的步骤如下:

  1. 重写 run 方法:确定线程的业务逻辑
  2. 调用 start 方法:让线程独立执行

2.2 线程中断机制

2.2.1 线程中断机制

一个线程不应该由其他线程来强制中断或停止,而是应该由线程自己自行停止,自己来决定自己的命运。所以Thread.stop、Thread.suspend、Thread.resume都已经被废弃了。

线程中断机制:Java中没有办法立即停止一条线程,然后停止线程却显得尤为重要,如取消一个耗时操作。因此,Java中提供了一种用于停止线程的协商机制(中断),也即中断表示协商机制。Java并没有给中断增加任何语法,中断的过程完全需要自己实现。

若要中断一个线程,你需要手动调用该线程的 interrupt 语法,该方法也仅仅是将线程对象的中断标识设置为 true,接着你需要自己写代码不断检查当前的线程的标识位,如果为 true ,表示别的线程请求这条线程中断,此时究竟该做什么需要程序员写代码实现。

每个线程对象中都有一个中断标识位,用于表示线程是否被中断。该标识位为 true 表示中断,为 false 表示未中断。通过调用线程对象的 interrupt 方法将该线程的标识位设置为 true,可以在别的线程中调用,也可以在自己的线程中调用。

2.2.2 中断线程的常见方式

  1. 通过共享的标记位来进行线程间通信
  2. volatile 修饰的变量保证内存可见性
  3. AtomicBoolean 原子类保证原子性及内存可见性
  4. 通过 interrupt 方法进行线程间通知:仅仅设置现成的中断状态为 true,发起一个协商而不会立刻停止线程。
  5. interrupted:判断线程是否被中断(返回当前线程的中断状态)并清除当前中断状态(设置为false)
  6. 有可能两次调用的结果是不同的
  7. isInterrupted:判断当前线程是否被中断
2.2.2.1 使用自定义的标志位结合 volatile 实现
public class InterruptDemo {// 保证内存可见性static volatile boolean isStop = false;public static void main(String[] args) {new Thread(()->{while(true){if(isStop){System.out.println(Thread.currentThread().getName()+"\t"+"stop");break;}System.out.println("Hello");}},"t1").start();try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {throw new RuntimeException(e);}new Thread(()->{isStop = true;},"t2").start();}
}

注意事项:

  1. Lambda表达式能够访问外面的局部变量的前提是该变量被final或者是‘实际final(代码中未对该变量做出修改)’。这样设计的目的是因为“变量捕获”。避免:如果外面的代码要对这个变量进行修改,就会出现一个情况,外面的变量变了里面的没变,代码更容易出现歧视。
  1. isQuit从成员变量改为局部变量,导致程序无法正常运行

相关文章:

  • 全面掌握 Jetpack Compose 的 State 体系:核心用法与最佳实践
  • 深入理解线程死锁:从概念到 Java 实战
  • 【win11 】win11 键盘测试
  • 【Python】存储机制和容器四大件列表、元组、字典、集合
  • 【言语理解】中心理解题目之选项分析
  • Java捕获InterruptedException异常后,会自动清空中断状态
  • 卷积神经网络实战(2)
  • [ML]通过50个Python案例了解深度学习和神经网络
  • VulnHub-OSCP靶机
  • 【神经网络与深度学习】生成模型-单位高斯分布 Generating Models-unit Gaussian distribution
  • 超详细讲解C语言转义字符\a \b \r \t \? \n等等
  • 单调栈与单调队列(c艹)、可视化Qt?
  • Android第三次面试总结之网络篇补充
  • 使用 Hugging Face 镜像站快速下载大模型
  • emplace_back和push_back
  • 五、shell脚本--函数与脚本结构:搭积木,让脚本更有条理
  • Vultr之Ubuntu重设密码
  • 解决在 Linux 中 WPS 字体缺失问题
  • KAG:通过知识增强生成提升专业领域的大型语言模型(三)
  • 有关水下图像增强的论文
  • 体坛联播|拜仁提前2轮德甲夺冠,赵心童11比6暂时领先
  • 福建两名厅级干部履新,张文胜已任省委省直机关工委副书记
  • 市场驱动的系统改造:丹麦零弃风经验研究
  • 全国铁路旅客发送量连续3天同比增幅超10%,今日预计发送1800万人次
  • 陈颖已任上海黄浦区委常委、统战部部长
  • 人民日报评论员:因势利导对经济布局进行调整优化