探索多线程编程:线程的本质、状态和属性

目录

  • 什么是线程
  • 线程状态
    • 新建线程
    • 可运行线程
    • 阻塞和等待线程
    • 终止线程
  • 线程属性
    • 优先级
    • 线程名
    • 守护线程
    • 中断线程
    • 未捕获异常的处理器

在现代计算机编程中,多线程是一个重要而强大的概念。它使得我们能够更有效地利用多核处理器、提高程序性能并实现并发操作。

什么是线程

线程是程序执行的最小单元,它是操作系统调度的基本单位。与进程不同,线程共享相同的进程内存空间,这意味着它们可以访问相同的数据和资源。线程之间的通信更加轻松,但也需要更仔细的同步,以避免竞态条件和数据冲突。
每个任务在一个线程中执行,线程是控制线程的简称。一个程序同时运行多个线程,就可以称这个程序是多线程的。
我们来写一个多线程程序看一下执行结果:

public class main {public static void main(String[] args) {//构造一个新线程Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 200; i++) {System.out.println("这是第一个线程!");}}});Thread t2 = new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 200; i++) {System.out.println("这是第二个线程!");}}});System.out.println("线程1启动");//启动新线程t1.start();System.out.println("线程2启动");t2.start();}
}

在这里插入图片描述
通过结果我们可以看到两个线程是同时执行的。
创建线程的几种方法可以看完之前写的博客。

线程状态

线程有如下6种状态:

  • New(新建)
  • Runnable(可运行)
  • Blocked(阻塞)
  • Waiting(等待)
  • Time waiting(计时等待)
  • Terminated(终止)

新建线程

用new操作符创建一个新线程时,这个线程还没有开始运行。
例如:

        //构造一个新线程Thread t1 = new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 200; i++) {System.out.println("这是第一个线程!");}}});

可运行线程

当新创建的线程调用start方法后,就处于可运行状态。一个可运行的线程可能处于正在运行状态也可能没有运行。这是因为抢占式调度系统,给每一个可运行线程一个时间片来执行任务。每一个处理器运行一个线程,当线程的数目多于处理器数目时,调度器需要分配时间片,让多个线程并行运行。

阻塞和等待线程

当线程处于阻塞或者等待状态时,它是暂时不活动的。

  • 线程试图获取内部的对象锁,而这个锁被其他线程占有,以至线程处于阻塞状态。
  • 线程等待其他线程发出的通知或中断信号。例如调用Object.wait方法,Thread.join方法使线程进入等待状态。
  • 还有就是使用Thread.sleep,Object.wait,Thread.join方法使使线程进入计时等待状态。

例如:Thread.sleep(1000);使线程等待一秒。

终止线程

  • run方法正常退出,线程自然结束
  • 一个没有捕获的异常终止了run方法,使线程意外终止

我们可以通过getState()得到当前线程的状态。

线程属性

线程的属性是指线程的一些特征和配置选项,它们可以影响线程的行为和性能。

优先级

优先级用于确定线程在竞争CPU时间时的优先级,即决定了线程被调度执行的概率。每个线程都有一个默认优先级,通常为普通(Normal)优先级,范围从1(最低优先级)到10(最高优先级)。线程的优先级可以通过编程方式进行设置和调整。

线程的优先级决定了它在与其他线程竞争CPU时间时的优先顺序。操作系统的调度算法通常会考虑线程的优先级来决定将CPU时间分配给哪个线程。高优先级线程相对于低优先级线程来说,有更高的概率获得CPU时间片,即有更多的机会去执行任务。然而,优先级并不是绝对的,只是一个相对的概念,高优先级线程并非一定比低优先级线程先执行。

下面通过一个简单的例子来解释优先级:

public class test1 implements Runnable {public void run() {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + " is running");}}public static void main(String[] args) {Thread thread1 = new Thread(new test1());Thread thread2 = new Thread(new test1());thread1.setPriority(Thread.MIN_PRIORITY); // 设置线程1的优先级为最低thread2.setPriority(Thread.MAX_PRIORITY); // 设置线程2的优先级为最高thread1.start();thread2.start();}
}

在这里插入图片描述
在上述例子中,我们创建了两个线程 thread1 和 thread2,并将它们分别设置为最低优先级和最高优先级。在 run 方法中,每个线程会循环打印自己的名称。由于线程2的优先级更高,它具有更高的CPU时间片分配概率,因此它更有可能在竞争中先被调度执行。但是,该结果并不是绝对的,线程1仍然有机会在某些情况下先于线程2执行。

线程名

线程名用于为线程赋予一个可识别和标识的名称。每个线程都可以被命名,这样在调试和日志记录时就能更容易地识别和追踪线程的执行情况。线程名可以帮助我们区分不同的线程并理解它们在程序中的作用。
在Java中,可以通过setName方法为线程设置名字,也可以通过getName方法获取线程的名称。线程名通常是一个描述性的字符串,可以根据任务的特性和上下文进行命名,以便更好地反映线程的功能。

守护线程

守护线程(Daemon Thread)是指在程序运行过程中在后台默默执行的线程,它并不会阻止程序的退出。当所有非守护线程结束时,守护线程会自动终止。它们通常用于执行一些后台任务或提供一种服务性功能,而不需要干扰或阻塞主程序的正常执行。
守护线程的生命周期与程序的生命周期相伴而终。当所有非守护线程都结束时,守护线程会被自动停止,即使它们正在执行某些任务。为了标识一个线程为守护线程,可以使用线程对象的setDaemon(true)方法设置,这一方法必须在线程启动前调用

中断线程

中断线程是指在多线程编程中,一个线程被要求停止执行或被强制终止。这通常是通过发送一个中断信号或设置一个标志来实现的,让线程在接收到中断请求后,安全地停止执行并释放资源。中断线程的目的通常是为了避免线程无法正常退出或处理某些异常情况。
下面是一个简单的Java示例,演示了如何中断一个线程:


public class InterruptExample {public static void main(String[] args) {Thread myThread = new Thread(new MyRunnable());myThread.start(); // 启动线程// 主线程等待一段时间后中断myThreadtry {Thread.sleep(2000); // 等待2秒钟myThread.interrupt(); // 发送中断信号} catch (InterruptedException e) {e.printStackTrace();}}static class MyRunnable implements Runnable {@Overridepublic void run() {while (!Thread.currentThread().isInterrupted()) {System.out.println("线程正在执行...");try {Thread.sleep(1000); // 线程每隔1秒钟执行一次} catch (InterruptedException e) {// 捕获到中断信号后,线程会退出循环System.out.println("线程被中断,即将退出...");Thread.currentThread().interrupt(); // 重新设置中断状态}}}}
}

在这里插入图片描述

在上述示例中,我们创建了一个线程(myThread),然后在主线程中等待2秒钟后发送中断信号给myThread。在MyRunnable线程中,线程不断地执行,但会检查是否接收到中断信号。如果接收到中断信号,线程会在捕获到InterruptedException后退出循环,完成线程的中断操作。
需要注意的是,中断线程并不会强制终止线程,而是通过设置一个中断标志,让线程在合适的时候自行终止。这样可以确保线程在终止时能够完成必要的清理工作,以避免资源泄漏和不一致的状态

interrupted和isInterrupted,interrupted方法是一个静态方法,它检查当前线程是否被中断,并且会清除该线程的中断状态,isInterrupted是一个实例方法,用来检查是否有线程被中断。

未捕获异常的处理器

未捕获异常处理器(Uncaught Exception Handler)是在多线程或多线程应用程序中用来处理未捕获异常的一种机制。当一个线程抛出一个未捕获的异常时,如果该线程没有显式地捕获这个异常,那么异常会传递到线程的未捕获异常处理器中,这个处理器可以自定义,用于记录异常信息、执行特定的操作,或者进行应用程序的安全退出。
下面是一个简单的Java示例,演示了如何设置未捕获异常处理器:


public class UncaughtExceptionHandlerExample {public static void main(String[] args) {// 设置未捕获异常处理器Thread.setDefaultUncaughtExceptionHandler(new CustomExceptionHandler());// 创建一个线程并启动它,该线程会抛出一个未捕获异常Thread thread = new Thread(() -> {throw new RuntimeException("这是一个未捕获的异常");});thread.start();}static class CustomExceptionHandler implements Thread.UncaughtExceptionHandler {@Overridepublic void uncaughtException(Thread t, Throwable e) {System.err.println("线程 " + t.getName() + " 抛出了未捕获的异常: " + e.getMessage());// 在这里可以添加自定义处理逻辑,如记录日志、发送通知等}}
}

在这里插入图片描述

在上述示例中,我们首先通过Thread.setDefaultUncaughtExceptionHandler方法设置了一个自定义的未捕获异常处理器(CustomExceptionHandler)。然后,创建了一个线程并启动它,该线程会故意抛出一个未捕获的异常。当这个异常抛出时,它会传递到我们设置的未捕获异常处理器中,CustomExceptionHandler中的uncaughtException方法将会执行,打印异常信息。您可以在这个方法中添加任何您需要的自定义处理逻辑,比如记录日志或发送通知。

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

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

相关文章

route命令小结

Destination: 如果不满足该列的任何一个ip,则走默认的default Gataway: *是 不指定gateway.有的系统是0.0.0.0,与*意义相同 Genmask: 0.0.0.0是不指定掩码, 255.255.0.0掩码了16位,172.17 开头的ip,会走这个网关 255.255.255.0掩码了16位,192.168.0 开头的ip都会走这个网关 当是…

探讨前后端分离开发的优势、实践以及如何实现更好的用户体验?

随着互联网技术的迅猛发展&#xff0c;前后端分离开发已经成为现代软件开发的一种重要趋势。这种开发模式将前端和后端的开发工作分开&#xff0c;通过清晰的接口协议进行通信&#xff0c;旨在优化开发流程、提升团队协作效率&#xff0c;并最终改善用户体验。本文将深入探讨前…

sentinel加密狗使用及规则配置

Sentinel加密狗是一种硬件加密设备&#xff0c;用于保护软件应用程序免受未经授权的访问和复制。它可以提供软件许可管理、访问控制和数据保护等功能。下面是Sentinel加密狗的使用及规则配置的相关介绍。 Sentinel加密狗的使用 插入加密狗&#xff1a;将Sentinel加密狗插入计算…

链条输送机如何润滑

润滑是使用机械设备过程中不可或缺的保养工作&#xff0c;链条输送机也不例外&#xff0c;但对于第一次使用链条机的用户来讲&#xff0c;对于哪个部位需要润和以及如何润滑都是一头雾水&#xff0c;今天艾讯就从专业的角度来和您分享一下链条输送机如何润滑的问题。 1、应切断…

爬虫进阶-反爬破解5(selenium的优势和点击操作+chrome的远程调试能力+通过Chrome隔离实现一台电脑登陆多个账号)

目录 一、selenium的优势和点击操作 二、chrome的远程调试能力 三、通过Chrome隔离实现一台电脑登陆多个账号 一、selenium的优势和点击操作 1.环境搭建 工具&#xff1a;Chrome浏览器chromedriverselenium win用户&#xff1a;chromedriver.exe放在python.exe旁边 MacO…

文件上传漏洞

任意文件上传 1. 概述 文件上传是Web 应用必备功能之一&#xff0c;如&#xff0c;头像上传&#xff0c;附件分享等。如果服务器配置不当或者没有进行足够的过滤&#xff0c;Web 用户就可以上传任意文件&#xff0c;包括恶意脚本文件&#xff0c;exe 程序等等&#xff0c;这就…

MySQL 连接出现 Authentication plugin ‘caching_sha2_password‘ cannot be loaded

在使用Navicat Premium 12连接MySQL数据库时会出现Authentication plugin caching_sha2_password cannot be loaded 出错 出现这个原因是mysql8 之前的版本中加密规则是mysql_native_password,而在mysql8之后,加密规则是caching_sha2_password, 解决问题方法&#xff1a;把my…

祝贺埃文科技入选河南省工业企业数据安全技术支撑单位

近日&#xff0c;河南省工业信息安全产业发展联盟公布了河南省工业信息安全应急服务支撑单位和河南省工业企业数据安全技术支撑单位遴选结果,最终评选出19家单位作为第一届河南省工业信息安全应急服务支撑单位和河南省工业企业数据安全技术支撑单位。 埃文科技凭借自身技术优势…

Redis集群服务器

集群简介 试想有一家餐厅&#xff0c;如果顾客人数较少&#xff0c;那么餐厅只需要一个服务员即可&#xff0c;如图1。但是&#xff0c;当顾客人数非常多时&#xff0c;一个服务员是绝对不够的&#xff0c;如图2。此时&#xff0c;餐厅需要雇用更多的服务员来解决大量访问&…

vue-tour新手指导,点击按钮,进行提示,再次点击按钮,提示隐藏,点击下一步,弹框显示

先看效果图 main.js中引入vue-tour import VueTour from vue-tour require(vue-tour/dist/vue-tour.css) Vue.use(VueTour)建一个登录页面 点击导航助手按钮&#xff0c;开始提示 <el-button type"primary" plain click"startTour">导航助…

信息技术 安全技术 信息安全管理测量

声明 本文是学习信息技术 安全技术 信息安全管理 测量. 而整理的学习笔记,分享出来希望更多人受益,如果存在侵权请及时联系我们 范围 为了评估按照GB/T 22080-2008规定实施的信息安全管理体系&#xff08;Information Security Management System&#xff0c;简称ISMS&#…

阿里巴巴API接口解析,实现按关键字搜索商品

要解析阿里巴巴API接口并实现按关键字搜索商品&#xff0c;你需要进行以下步骤&#xff1a; 了解阿里巴巴API接口文档&#xff1a;访问阿里巴巴开放平台&#xff0c;找到API文档&#xff0c;了解阿里巴巴提供的API接口以及相关的参数、返回值等信息。注册开发者账号&#xff1…