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

多线程的五种“打开”方式

1 概念

1.1 线程是什么??

线程(Thread)是计算机科学中的一个基本概念,它是进程(Process)中的一个执行单元,负责执行程序的指令序列。线程是操作系统能够进行调度和执行的最小单位。在多任务操作系统中,多个线程可以在同一个进程内并发执行,共享进程的资源。

{

假设你正在厨房中准备晚餐,这个过程中有多个线程在运行,每个线程代表一个不同的烹饪任务。这些线程可以同时执行,以加速整个烹饪过程,就像多线程在计算机程序中一样。

  1. 主厨线程:这个线程负责协调整个烹饪过程。主厨线程制定了食谱和指导其他线程如何协同工作。

  2. 切菜线程:这个线程负责将食材切成适当的大小和形状。它可以在切菜板上进行多个切割任务,以提高效率。

  3. 炉灶线程:这个线程负责在炉灶上烹饪不同的菜肴。例如,一个线程可以煮汤,另一个线程可以煎肉,它们可以同时工作,以节省时间。

  4. 烤箱线程:如果你需要烤一道菜,那么烤箱线程可以负责在烤箱中烘烤食物,同时其他线程继续处理其他任务。

  5. 洗碗线程:一旦完成烹饪,就有一个线程负责洗碗和清理厨房。这个线程可以与其他线程并发运行,以确保整个晚餐流程的顺利结束。

在这个例子中,每个线程都代表一个不同的烹饪任务,它们可以并行工作,以提高烹饪效率,就像多线程在计算机程序中允许不同任务并发执行一样

}

1.2  为什么要使用线程??

1 “并发编程”成为“刚需”

        单核CPU的发展遇到了瓶颈,想要提高算力,就需要多核CPU。而并发编程能够充分利用多核CPU资源;

        有些任务场景需要“等待IO”,为了让等待的时间去做一些其他工作,也需要使用到并发编程。

2. 虽然进程也能够实现并发编程,但是线程比进程更加轻量级。

  • 创建线程比创建进程更快.
  • 销毁线程比销毁进程更快.
  • 调度线程比调度进程更快.

1.3 进程和线程的区别??

  • 进程是包含线程的。每个进程至少有一个线程的存在,也就是主线程;
  • 进程和线程之间不共享内存空间。同一个进程的线程之间共享同一内存空间;
  • 进程是系统分配资源的最小单位,线程是操作系统调度的最小单位;
  • 进程是相互独立的,一个进程的崩溃通常不会影响其他进程。线程之间更密切相关,一个线程的错误可能会影响到同一进程中的其他线程。
  • 创建和销毁进程通常比线程昂贵,因为进程需要分配和释放独立的内存空间和资源。线程的创建和销毁通常更快,因为它们共享进程的资源,不需要分配独立的内存空间。

1.4 Java的线程和操作系统的线程的区别??

  • 线程是操作系统中的概念. 操作系统内核实现了线程这样的机制, 并且对用户层提供了一些 API 供用户使用(例如 Linux pthread ).
  • Java 标准库中 Thread 类可以视为是对操作系统提供的 API 进行了进一步的抽象和封装.

2 感受多线程代码

多线程和普通程序最大的区别就是每个线程都是独立的执行流 多线程之间是并发执行的。

public class ThreadDemo {private static class MyThread extends Thread{@Overridepublic void run() {Random random = new Random();while (true){// 打印主线程名称System.out.println(Thread.currentThread().getName());try {Thread.sleep(random.nextInt(10));//随机停止运行0-9秒} catch (InterruptedException e) {e.printStackTrace();}}}}public static void main(String[] args) {MyThread t1 = new MyThread();MyThread t2 = new MyThread();MyThread t3 = new MyThread();//启动并创建线程工作t1.start();t2.start();t3.start();//主线程工作Random random = new Random();while (true){// 打印主线程名称System.out.println(Thread.currentThread().getName());try {Thread.sleep(random.nextInt(10));//随机停止运行0-9秒} catch (InterruptedException e) {e.printStackTrace();}}}
}

结果:

我们可以使用JDK提供的jconsole命令观察线程(在jdk的bin目录下面)

3 创建线程的“五种”方式

方法1 继承Thread类

public class ThreadDemo1 {static class MyThread extends Thread{//重写run方法  run描述该线程要干的活是什么@Overridepublic void run() {System.out.println("我是一个线程 hello thread!");}//run方法执行完毕后 新的这个线程就会被销毁}public static void main(String[] args) {Thread thread = new MyThread();//thread类不需要任何包??为什么还有哪些我们见过的 出现这种情况 java.lang包下面的是不用导包的 比如string stirngbuilderthread.start();//线程中的启动方法 start创建了一个新线程 有新线程来执行run方法}
}

方法2 实现Runnable 接口

// Runnable 作用就是描述一个“要执行的任务” run方法就是任务的执行细节
class MyRunnable implements Runnable{@Overridepublic void run() {System.out.println("hello thread-runnable");}
}public class ThreadDemo2 {public static void main(String[] args) {// new Runnable就是描述一个任务MyRunnable runnable = new MyRunnable();//然后将这个任务交给线程来执行Thread thread = new Thread(runnable);thread.start();thread.run();/** thread.run()是在当前线程中执行线程的任务,没有创建新的线程,不实现并发。thread.start()创建一个新的线程,并在新线程中执行线程的任务,实现了多线程并发。通常应该使用thread.start()来启动线程*/}
}

首先对比一下上面两种方法:

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

后面的方法都是前两者的“变形”:

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

//使用匿名内部类来实现线程
public class ThreadDemo3 {public static void main(String[] args) {Thread t = new Thread() {@Overridepublic void run() {System.out.println("匿名内部类实现thread");}};t.start();}
}

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

//使用匿名内部类
public class ThreadDemo4 {public static void main(String[] args) {Thread t = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("实现runnable-匿名内部类");}});t.start();}
}

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

//lambda
public class ThreadDemo5 {public static void main(String[] args) {Thread t = new Thread(() -> {System.out.println("hello thread");});t.start();}
}

相关文章:

多线程的五种“打开”方式

1 概念 1.1 线程是什么?? 线程(Thread)是计算机科学中的一个基本概念,它是进程(Process)中的一个执行单元,负责执行程序的指令序列。线程是操作系统能够进行调度和执行的最小单位。…...

信息熵 条件熵 交叉熵 联合熵 相对熵(KL散度) 互信息(信息增益)

粗略版快速总结 条件熵 H ( Q ∣ P ) 联合熵 H ( P , Q ) − H ( P ) 条件熵H(Q∣P)联合熵H(P,Q)−H(P) 条件熵H(Q∣P)联合熵H(P,Q)−H(P) 信息增益 I ( P , Q ) H ( P ) − H ( P ∣ Q ) H ( P ) H ( Q ) − H ( P , Q ) 信息增益 I(P,Q)H(P)−H(P∣Q)H(P)H(Q)-H(P,Q) 信息…...

Fiddler Response私人订制

在客户端接口的测试中,我们经常会需要模拟各种返回状态或者特定的返回值,常见的是用Fiddler模拟各种请求返回值场景,如重定向AutoResponder、请求拦截修改再下发等等。小编在近期的测试中遇到的一些特殊的请求返回模拟的测试场景,…...

【德哥说库系列】-ASM管理Oracle 19C单实例部署

📢📢📢📣📣📣 哈喽!大家好,我是【IT邦德】,江湖人称jeames007,10余年DBA及大数据工作经验 一位上进心十足的【大数据领域博主】!😜&am…...

手写一个简单爬虫--手刃豆瓣top250排行榜

#拿到页面面源代码 request #通过re来提取想要的有效信息 re import requests import re url"https://movie.douban.com/top250"headers{"user-agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/11…...

【word密码】如何限制word文件中部分内容?

Word文件中有一部分内容不想他人编辑,我们可以设置限制编辑,可以对一部分内容设置限制编辑,具体方法如下: 我们将需要将可以编辑的地方选中,然后打开限制编辑功能 然后勾选限制编辑设置界面中的【限制编辑】和【每个人…...

spring 自定义类型转换-ConverterRegistry

1背景介绍 一个应用工程里面,一遍会涉及到很多的模型转换,如DTO模型转DO模型,DO模型转DTO, 或者Request转DTO模型,总的来说,维护起来还是相对比较复杂。每涉及一个转换都需要重新写对应类的get或者set方法&#xff0c…...

springboot实现发送短信验证码

目录 一、选择并注册短信服务提供商: 二、添加依赖: 三、配置短信服务信息: 四、编写发送短信验证码的方法: 五、调用发送短信验证码的方法: 一、选择并注册短信服务提供商: 1、选择一个可靠的短信服…...

2024王道408数据结构P144 T18

2024王道408数据结构P144 T18 思考过程 首先还是先看题目的意思,让我们在中序线索二叉树里查找指定结点在后序的前驱结点,这题有一点难至少对我来说…我讲的不清楚理解一下我做的也有点糊涂。在创建结构体时多两个变量ltag和rtag,当ltag0时…...

在windows下安装配置skywalking

1.下载地址 Downloads | Apache SkyWalkinghttp://skywalking.apache.org/downloads/ 2.文件目录说明 将文件解压后,可看到agent和bin目录: Agent:作为探针,安装在服务器端,进行数据采集和上报。 Config&#xff1a…...

关于大模型参数微调的不同方法

Adapter Tuning 适配器模块(Adapter Moudle)可以生成一个紧凑且可扩展的模型;每个任务只需要添加少量可训练参数,并且可以在不重新访问之前任务的情况下添加新任务。原始网络的参数保持不变,实现了高度的参数共享 Pa…...

方法的引用第一版(method reference)

1、体验方法引用 在使用Lambda表达式的时候,我们实际上传递进去的代码就是一种解决方案:拿参数做操作那么考虑一种情况:如果我们在Lanbda中所指定的操作方案,已经有地方存在相同方案,那是否还有必要再重复逻辑呢&#…...

Android DataBinding 基础入门(学习记录)

目录 一、DataBinding简介二、findViewById 和 DataBinding 原理及优缺点1. findViewById的优缺点2. DataBinding的优缺点 三、Android mvvm 之 databinding 原理1. 简介和三个主要的实体DataViewViewDataBinding 2.三个功能2.1. rebind 行为2.2 observe data 行为2.3 observe …...

spring 错误百科

一、使用Spring出错根源 1、隐式规则的存在 你可能忽略了 Sping Boot 中 SpringBootApplication 是有一个默认的扫描包范围的。这就是一个隐私规则。如果你原本不知道,那么犯错概率还是很高的。类似的案例这里不再赘述。 2、默认配置不合理 3、追求奇技淫巧 4、…...

OpenCV基本操(IO操作,读取、显示、保存)

图像的IO操作,读取和保存方法 1.1 API cv.imread()参数: 要读取的图像 读取图像的方式: cv.IMREAD*COLOR:以彩色模式加载图像,任何图像的图像的透明度都将被忽略。这是默认参数 标志: 1 cv.IMREAD*GRAYSCALE :以…...

1.快速搭建Flask项目

一.Pear Admin Flask 官网文档:http://www.pearadmin.com/doc/index.html 1.1下载安装 # 下 载 git clone https://gitee.com/pear-admin/pear-admin-flask# 安 装 pip install -r requirements.txt1.2修改配置 applications下的config.py docker运行的修改dockerdata/conf…...

编程题四大算法思想(三)——贪心法:找零问题、背包问题、任务调度问题、活动选择问题、Prim算法

文章目录 贪心法找零问题(change-making problem)贪心算法要求基本思想适合求解问题的特征 背包问题0/1背包问题0/1背包问题——贪心法 分数背包问题 任务调度问题活动选择问题活动选择——贪心法最早结束时间优先——最优性证明 Prim算法 贪心法 我在当…...

core dump管理在linux中的前世今生

目录 一、什么是core dump? 二、coredump是怎么来的? 三、怎么限制coredump文件的产生? ulimit 半永久限制 永久限制 四、从源码分析如何对coredump文件的名字和路径管理 命名 管理 一些问题的答案 1、为什么新的ubuntu不能产生c…...

Springboot整合knife4j配置swagger教程-干货

开启swagger文档&#xff0c;直接上教程。 第一步:引入依赖 <!--swagger 依赖--><dependency><groupId>com.github.xiaoymin</groupId><artifactId>knife4j-spring-boot-starter</artifactId><version>3.0.3</version></d…...

C++ 中的 Pimpl 惯用法

C 中的 Pimpl 惯用法 介绍 Pimpl&#xff08;Pointer to Implementation&#xff09;是一种常见的 C 设计模式&#xff0c;用于隐藏类的实现细节&#xff0c;从而减少编译依赖和提高编译速度。本文将通过一个较为复杂的例子&#xff0c;展示如何使用智能指针&#xff08;如 s…...

零门槛NAS搭建:WinNAS如何让普通电脑秒变私有云?

一、核心优势&#xff1a;专为Windows用户设计的极简NAS WinNAS由深圳耘想存储科技开发&#xff0c;是一款收费低廉但功能全面的Windows NAS工具&#xff0c;主打“无学习成本部署” 。与其他NAS软件相比&#xff0c;其优势在于&#xff1a; 无需硬件改造&#xff1a;将任意W…...

Cursor实现用excel数据填充word模版的方法

cursor主页&#xff1a;https://www.cursor.com/ 任务目标&#xff1a;把excel格式的数据里的单元格&#xff0c;按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例&#xff0c;…...

AI Agent与Agentic AI:原理、应用、挑战与未来展望

文章目录 一、引言二、AI Agent与Agentic AI的兴起2.1 技术契机与生态成熟2.2 Agent的定义与特征2.3 Agent的发展历程 三、AI Agent的核心技术栈解密3.1 感知模块代码示例&#xff1a;使用Python和OpenCV进行图像识别 3.2 认知与决策模块代码示例&#xff1a;使用OpenAI GPT-3进…...

day52 ResNet18 CBAM

在深度学习的旅程中&#xff0c;我们不断探索如何提升模型的性能。今天&#xff0c;我将分享我在 ResNet18 模型中插入 CBAM&#xff08;Convolutional Block Attention Module&#xff09;模块&#xff0c;并采用分阶段微调策略的实践过程。通过这个过程&#xff0c;我不仅提升…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

2.Vue编写一个app

1.src中重要的组成 1.1main.ts // 引入createApp用于创建应用 import { createApp } from "vue"; // 引用App根组件 import App from ./App.vue;createApp(App).mount(#app)1.2 App.vue 其中要写三种标签 <template> <!--html--> </template>…...

生成 Git SSH 证书

&#x1f511; 1. ​​生成 SSH 密钥对​​ 在终端&#xff08;Windows 使用 Git Bash&#xff0c;Mac/Linux 使用 Terminal&#xff09;执行命令&#xff1a; ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" ​​参数说明​​&#xff1a; -t rsa&#x…...

第 86 场周赛:矩阵中的幻方、钥匙和房间、将数组拆分成斐波那契序列、猜猜这个单词

Q1、[中等] 矩阵中的幻方 1、题目描述 3 x 3 的幻方是一个填充有 从 1 到 9 的不同数字的 3 x 3 矩阵&#xff0c;其中每行&#xff0c;每列以及两条对角线上的各数之和都相等。 给定一个由整数组成的row x col 的 grid&#xff0c;其中有多少个 3 3 的 “幻方” 子矩阵&am…...

NXP S32K146 T-Box 携手 SD NAND(贴片式TF卡):驱动汽车智能革新的黄金组合

在汽车智能化的汹涌浪潮中&#xff0c;车辆不再仅仅是传统的交通工具&#xff0c;而是逐步演变为高度智能的移动终端。这一转变的核心支撑&#xff0c;来自于车内关键技术的深度融合与协同创新。车载远程信息处理盒&#xff08;T-Box&#xff09;方案&#xff1a;NXP S32K146 与…...

AGain DB和倍数增益的关系

我在设置一款索尼CMOS芯片时&#xff0c;Again增益0db变化为6DB&#xff0c;画面的变化只有2倍DN的增益&#xff0c;比如10变为20。 这与dB和线性增益的关系以及传感器处理流程有关。以下是具体原因分析&#xff1a; 1. dB与线性增益的换算关系 6dB对应的理论线性增益应为&…...