每个程序至少有一个线程 —— 主线程

主线程是程序的起点,你可以从它开始创建新的线程来执行任务。为此,你需要创建自定义线程,编写在线程中执行的代码,并启动它。

通过继承创建自定义线程

创建新线程有两种主要方式:

  1. 继承 Thread 类并重写其 run 方法

  2. 实现 Runnable 接口,并将实现类传递给 Thread 类的构造函数

下面是继承 Thread 类并重写 run 方法的示例:

class HelloThread : Thread() {override fun run() {val helloMsg = "Hello, i'm $name"println(helloMsg)}
}

而下面是实现 Runnable 接口并传递给 Thread 构造函数的示例:

class HelloRunnable : Runnable {override fun run() {val threadName = Thread.currentThread().nameval helloMsg = "Hello, i'm $threadName"println(helloMsg)}
}

这两种方式都需要你重写 run 方法,它是一个普通的方法,包含了你要执行的代码。选择哪种方式取决于具体任务和个人偏好。

如果你继承了 Thread 类,可以直接使用其字段和方法,但 Kotlin 不支持多重继承,所以你不能再继承其他类。

创建线程对象

Thread 类有很多构造函数,我们来看其中几个示例:

val t1 = HelloThread()              // 使用子类
val t2 = Thread(HelloRunnable())    // 传入 Runnable 实现
val myThread = Thread(HelloRunnable(), "my-thread") // 指定线程名

如果你想在 HelloThread 类中设置线程名,需要重写构造函数。

因此,实现 Runnable 接口是一种更灵活的方式。

使用 Lambda 更简单

如果你已经熟悉 Lambda 表达式,可以用下面这种方式:

val t3 = Thread {println("Hello, i'm ${Thread.currentThread().name}")
}

更简便的线程创建方式

如果不想继承或实现接口,也可以使用 thread(...) 函数创建线程,它来自 kotlin.concurrent 包:

import kotlin.concurrent.threadval t4 = thread(start = false, name = "Thread 4", block = {println("Hello, I'm ${Thread.currentThread().name}")
})

该函数的参数包括:

  • start:是否立即启动线程;

  • isDaemon:是否为守护线程;

  • contextClassLoader:类加载器;

  • name:线程名称;

  • priority:优先级;

  • block:线程执行代码块。

启动线程

使用 Thread 类的 start() 方法启动线程。调用后,run 方法会在新线程中自动执行,但不会立刻执行

示例:

fun main() {val t = thread(start = false, block = {println("Hello, I'm ${Thread.currentThread().name}")})t.start()
}

或者直接设置 start = true(默认值):

fun main() {val t = thread(block = {println("Hello, I'm ${Thread.currentThread().name}")})
}

输出示例:

Hello, i'm Thread-0

启动线程的内部原理

线程启动不会立即执行,启动与运行之间存在延迟。线程默认是非守护线程

  • 守护线程不会阻止 JVM 退出;

  • 非守护线程还在运行时,JVM 不会退出;

  • 守护线程通常用于后台任务。

注意

  • start() 会启动新线程并执行 run() 方法;

  • 直接调用 run() 不会启动新线程,只是在当前线程中执行;

  • 多次调用 start() 会抛出 IllegalThreadStateException

  • 多线程中的执行顺序是不可预测的,除非使用了额外的同步机制。

示例代码:

fun main() {val t1 = HelloThread()val t2 = HelloThread()t1.start()t2.start()println("Finished")
}

可能的输出顺序:

Hello, i'm Thread-1
Finished
Hello, i'm Thread-0

也可能是:

Finished
Hello, i'm Thread-0
Hello, i'm Thread-1

说明线程的启动顺序与实际运行顺序可能不同。

一个简单的多线程程序

下面是一个简单的多线程示例:

一个线程不断读取用户输入并打印其平方,主线程则间歇性输出消息。

工作线程类:

class SquareWorkerThread(name: String) : Thread(name) {override fun run() {while (true) {val number = readln().toInt()if (number == 0) {break}println(number * number)}println("$name's finished")}
}

主线程逻辑:

fun main() {val workerThread = SquareWorkerThread("square-worker")workerThread.start()for (i in 0 until 5_555_555_543L) {if (i % 1_000_000_000 == 0L) {println("Hello from the main!")}}
}

示例输入与输出(带注释):

Hello from the main!    // 主线程输出
2                       // 输入
4                       // 输出平方
Hello from the main!    // 主线程输出
3
9
5
Hello from the main!
25
0                       // 输入 0 终止线程
square-worker finished  // 工作线程结束提示
Hello from the main!
Hello from the main!

最终输出表明,两个线程并发执行。虽然不是真正同时,但每个线程都得到了执行的机会。


总结

  • 如何创建线程对象;

  • 如何设置线程执行的代码;

  • 如何启动线程;

  • 线程背后的工作原理;

  • 线程运行的非确定性;

  • 简单的多线程程序如何写。

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

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

相关文章

2025真实面试试题分析-安卓客户端开发

以下是对安卓客户端开发工程师面试问题的分类整理、领域占比分析及高频问题精选(基于​​85道问题,总出现次数118次​​)。按技术领域整合为​​7大核心类别​​,按占比排序并精选高频问题标注优先级(1-5🌟…

算法学习笔记:29.拓扑排序——从原理到实战,涵盖 LeetCode 与考研 408 例题

拓扑排序(Topological Sorting)是一种针对有向无环图(DAG)的线性排序算法,它将图中的顶点按照一定规则排列,使得对于图中的任意一条有向边 u→v,顶点 u 都排在顶点 v 之前。拓扑排序在任务调度、…

利用Web3加密技术保障您的在线数据安全

在这个信息爆炸的数字化时代,保护个人和企业数据安全变得尤为重要。Web3技术以其去中心化和加密特性,为在线数据安全提供了新的解决方案。本文将探讨Web3技术如何通过加密技术保障您的在线数据安全,并介绍如何有效利用这些技术。 什么是Web3技…

Vue实现el-checkbox单选并回显选中

先说需求 我要在页面进行checkbox单选并回显 第一步先把基本的页面写好噢&#xff1a;vue代码&#xff1a;别忘了写change啊<el-form-item label"按钮颜色:" prop"menuColor"><el-checkbox-group v-model"buttonColor" change"bin…

动态规划--序列找优问题【1】

一、说明 动态规划似乎针对问题很多&#xff0c;五花八门&#xff0c;似乎每一个问题都有一套具体算法。其实不是的&#xff0c;动态规划只有两类&#xff1a;1&#xff09;针对图的路径问题 2&#xff09;针对一个序列的问题。本篇讲动态规划针对序列的算法范例。 二、动态规划…

独家|百度副总裁尚国斌即将离职,此前统筹百度地图;行业搜索及智能体业务总经理谢天转岗IDG

百度人事再变动。作者|文昌龙编辑|杨舟据「市象」了解&#xff0c;近期&#xff0c;百度副总裁尚国斌即将离职。公开资料显示&#xff0c;尚国斌2010年毕业于南开大学&#xff0c;2012年加入百度&#xff0c;先后在商业分析部、集团战略办、智能驾驶事业群工作。尚国斌同样也在…

Qt 网络编程进阶:HTTP 客户端实现

在 Qt 应用程序中&#xff0c;实现高性能、可靠的 HTTP 客户端是常见需求。Qt 提供了丰富的网络模块&#xff0c;包括 QNetworkAccessManager、QNetworkRequest 和 QNetworkReply 等类&#xff0c;用于简化 HTTP 通信。本文将深入探讨 Qt 网络编程中 HTTP 客户端的进阶实现&…

Python Requests-HTML库详解:从入门到实战

一、库简介 Requests-HTML是Python中集网络请求与HTML解析于一体的全能型库&#xff0c;由知名开发者Kenneth Reitz团队维护。它完美结合了Requests的易用性和Parsel的选择器功能&#xff0c;并内置JavaScript渲染引擎&#xff0c;特别适合现代动态网页抓取。最新版本&#xf…

基于springboot的小区车位租售管理系统

博主介绍&#xff1a;java高级开发&#xff0c;从事互联网行业六年&#xff0c;熟悉各种主流语言&#xff0c;精通java、python、php、爬虫、web开发&#xff0c;已经做了六年的毕业设计程序开发&#xff0c;开发过上千套毕业设计程序&#xff0c;没有什么华丽的语言&#xff0…

Kafka 如何优雅实现 Varint 和 ZigZag 编码

ByteUtils 是 Kafka 中一个非常基础且核心的工具类。从包名 common.utils 就可以看出&#xff0c;它被广泛用于 Kafka 的各个模块中。它的主要职责是提供一套高效、底层的静态方法&#xff0c;用于在字节缓冲区 (ByteBuffer)、字节数组 (byte[]) 以及输入/输出流 (InputStream/…

局域网 IP地址

很多童鞋搞不清楚局域网ip是什么? 什么是局域网 IP 地址? 局域网 IP 地址,也称为 私有 IP 地址(Private IP Address),是用于在局域网内部标识设备的地址。这些地址不能直接在互联网上被访问,通常由路由器自动分配,用于设备之间的内部通信。 局域网 IP 地址的分类 根…

k8s的service、deployment、探针详解

1.k8s组成图2.service和deployment的流量转发图# Deployment 定义容器端口 apiVersion: apps/v1 kind: Deployment metadata:name: myapp spec:template:spec:containers:- name: nginximage: nginxports:- containerPort: 80 # 容器监听 80name: http # 端口命名&…

【PostgreSQL教程】PostgreSQL中json类型与jsonb类型的区别

博主介绍:✌全网粉丝23W+,CSDN博客专家、Java领域优质创作者,掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域✌ 技术范围:SpringBoot、SpringCloud、Vue、SSM、HTML、Nodejs、Python、MySQL、PostgreSQL、大数据、物联网、机器学习等设计与开发。 感兴趣的可…

牛客刷题记录01

除2&#xff01; 目录 除2&#xff01; 题目描述&#xff1a; ​编辑 题目解析&#xff1a; 代码实现&#xff1a; 数组中两个字符串的最小距离__牛客网 题目描述&#xff1a; 题目解析&#xff1a; 代码实现&#xff1a; 除2&#xff01; 题目描述&#xff1a; 给一个…

Docker Compose UI远程访问教程:结合贝锐花生壳实现内网穿透

对于很多刚接触Docker的用户来说&#xff0c;命令行操作总带着一丝“劝退感”。尤其是要在Windows上部署服务、开放端口、配置参数时&#xff0c;稍有不慎就容易出错。有没有办法像网页后台一样&#xff0c;用图形界面来管理Docker项目呢&#xff1f;答案是&#xff1a;有&…

HF83311_VB1/HF83311Q_VB1:高性能USB HiFi音频解码器固件技术解析

引言随着高品质音频体验需求的不断增长&#xff0c;音频解码器固件的性能和功能成为决定音频设备品质的关键因素。本文将介绍一款基于XMOS XU316技术的高性能USB HiFi音频解码器固件——HF83311_VB1/HF83311Q_VB1&#xff0c;这是一款专为USB HiFi音频应用设计的软件解决方案。…

[ComfyUI] -入门1-ComfyUI 是什么?比 Stable Diffusion WebUI 强在哪?

ComfyUI 是一个开源的、节点可视化界面,用于构建与执行 Stable Diffusion 图像生成流程。它把复杂的生成过程拆解为许多“节点”(如提示编码、采样器、控制网络等),用户通过连接节点,就能自由编排工作流 。这种设计适合开发者与进阶用户,更便于微调、多分支与复用流程。 …

[python][flask]flask接受get或者post参数

在 Flask 中&#xff0c;可以通过 request 对象来获取客户端通过 GET 或 POST 方法发送的参数。以下是如何在 Flask 中接收 GET 和 POST 参数的详细说明&#xff1a;1. 接收 GET 参数GET 请求的参数通常通过 URL 的查询字符串传递。例如&#xff0c;对于 URL http://example.co…

Creo 模块众多,企业如何按需灵活分配许可证资源?

在数字化设计与智能制造深入发展的当下&#xff0c;企业 CAD/CAE 工具的精细化管理越来越重要。Creo&#xff0c;作为 PTC 旗下一体化 3D CAD 平台&#xff0c;以其模块化、可扩展的产品架构&#xff0c;广泛应用于机械、装备、汽车、航空航天等行业。其丰富的模块库覆盖建模设…

【c++】提升用户体验:问答系统的交互优化实践——关于我用AI编写了一个聊天机器人……(12)

本期依旧使用豆包辅助完成代码。从功能到体验的转变上个版本已经实现了问答系统的核心功能&#xff1a;基于 TF-IDF 算法的问题匹配和回答。它能够读取训练数据&#xff0c;处理用户输入&#xff0c;并返回最相关的答案。但在用户体验方面还有很大提升空间。让我们看看改进版做…