javaEE-多线程编程-3

embedded/2024/12/21 21:52:58/

目录

java%20%E5%B8%B8%E8%A7%81%E7%9A%84%E5%8C%85%20%3A-toc" style="margin-left:0px;">java 常见的包 :

回调函数:

什么是线程:

第一个线程:

验证多线程执行:

内核:

调用sleep()方法:

执行结果分析:

线程创建的几种方式:

1.继承Thread类,重写run()方法.

2.实现Runnable接口,重写run()方法.

3.继承Thread类,重写run()方法.但使用匿名内部类

4.实现Runnable接口,重写run()方法,但使用匿名内部类:

5.使用lambda表达式(推荐)

Thread的构造方法

Thread的常用的属性:

1.ID:jvm自动分配的身份标识,不同线程不会重复

2.名称是调试的时候用到的

3.状态:

4.优先级:

5.是否后台线程:

6.是否存活:


在写代码的时候,可以用多进程编程,也可以用多线程编程.

多进程编在java中不太推荐,因为与多进程编程相关的api,在java标准库中都没有提供.

系统提供了多线程编程的api,在java标准库中,把这些api都封装了,在代码中可以直接使用.

并且在面对频繁创建和销毁进程的时候,多线程编程具有非常大的优势.效率非常高.

java%20%E5%B8%B8%E8%A7%81%E7%9A%84%E5%8C%85%20%3A" style="background-color:transparent;">java 常见的包 :

1. java.lang:系统常用基础类(String、Object),此包从JDK1.1后自动导入。

2. java.lang.reflect:java 反射编程包;

3. java.net:进行网络编程开发包。

4. java.sql:进行数据库开发的支持包。

5. java.util:是java提供的工具程序包。(集合类等) 非常重要

6. java.io:I/O编程开发包

Thread类就是java.long包下的类,不需要引入包就能直接使用.

一个.java文件中,只能有一个类被public修饰,若该类没有被public修饰,就只能在该包中,被别的类引用.

一个进程至少会有一个线程,该进程的第一个线程就是main线程,也就是主线程的入口方法.

回调函数:

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

简单来说:回调函数就是把一段代码,向传参一样,传递给其它代码,这段代码会在某个时刻被调用执行.这就叫做回调.

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。

回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。如果代码立即被执行就称为 同步回调,如果过后再执行,则称之为 异步回调。

什么是线程:

⼀个线程就是⼀个"执⾏流".每个线程之间都可以按照顺序执⾏⾃⼰的代码.多个线程之间"同时"执⾏ 着多份代码

第一个线程:

创建一个Thread01类,让该类继承Thread类,重写Thread类的run()方法,

在主函数中实例化该类,调用该类的start()方法,这样,不需要我们手动调用run()方法,待线程创建好后,会在合适的时机被jvm自动调用.(这种风格的函数,就被称为"回调函数"callback)

调⽤start()⽅法,才真的在操作系统的底层创建出⼀个线程.

java">package Thread_;class MyThread01 extends Thread{@Overridepublic void run() {//重写run()方法//run()方法就是该线程的入口while (true){System.out.println("Thread run");}}
}
public class Thread01 {public static void main(String[] args) {Thread thread01 = new MyThread01();thread01.start();//必须要调用start()方法,才能开启线程while(true){System.out.println("main ");}}
}

当引入多线程之后,代码中就可以同时具备多个执行流了.

验证多线程执行:

可以通过jdk/bin/jconsloe.exe文件看进程状态.

先运行自己写的代码,让后进行下面的操作

内核:

操作系统的内核是操作系统最核心的功能模块.(管理硬件,给软件提供稳定的运行环境)

简单来说:内核态是非常重要的,不允许用户修改的,划分出用户态和内核态也是目的是为了稳定,以防自己的应用程序把硬件设备或软件资源给搞坏了.

操作系统=内核+应用程序.

一旦开始执行,线程就会飞快的循环起来,使cpu占用率较高,进一步提高电脑的功耗,为了不让循环跑的那么快,可以在循环体中设置Thread类的sleep()方法,让每隔一定时间运行一次,这样就能降低电脑的功耗.

调用sleep()方法:

sleep()方法调用时,会有受查异常,需要手动抛出.

Mythread类中的run()方法内的异常抛出只能以try-catch的形式,不能以throws的形式,因为run()方法是重写父类的方法,父类没有throws这个异常,若加上throws,就修改了方法签名,因此,子类重写run()方法的时候,也就只能以try-catch的形式抛出异常了.

以try-catch的形式抛出异常:

以throws的形式抛出异常:

时间转换单位:

1s=1000ms(毫秒)

1ms=1000(微妙)

1um=1000nm(纳秒)

上面的第一个线程代码,可以看出,main()方法中有一个死循环,在Thread01类的run()方法中也有一个死循环,一般来说,一个代码中出现两个死循环,只会运行一个,但实际上这两个死循环中的代码都被运行了,这就说明是两个线程在同时执行.

执行结果分析:

从执行的结果上可以看出,thread和main是随机交替出现的,也就是说,每隔一秒钟,thread和main被执行一次,但是谁先被执行,是无法确定的.

但能看出,每次最开始执行的时候,都是main第一次被执行,这是因为在创建MyThrow01线程的时候,还是会有开销的,这个开销比创建进程要低很多(但也不是没有),就是这一点点的开销,使得main线程每次在最开始的时候先执行.

(注意:main线程是第一线程)

线程创建的几种方式:

1.继承Thread类,重写run()方法.

也就是上面的这种方式.

java">package Thread_;class MyThread01 extends Thread{@Overridepublic void run() {//run()方法就是该线程的入口while (true){System.out.println("Thread run");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}
public class Thread01 {public static void main(String[] args) {Thread thread01 = new MyThread01();thread01.start();//必须要调用start()方法,才能开启线程while(true){System.out.println("main ");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}

2.实现Runnable接口,重写run()方法.

Runnable接口需要搭配Thread类使用,才能真正在系统中创建出线程来
java">package Thread_;class MyThread02 implements Runnable{@Overridepublic void run() {while(true){System.out.println("Thread01 run()");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}
public class Thread02 {public static void main(String[] args) {MyThread02 runnable = new MyThread02();Thread thread1 = new Thread(runnable);//Runnable接口需要搭配Thread类使用,才能真正在系统中创建出线程来thread1.start();while(true){System.out.println("main()");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
}

3.继承Thread类,重写run()方法.但使用匿名内部类

java">Thread t=new Thread(){//这里写的{}表示要定义一个类,并且这个新类继承Thread,//且没有名字,用一次就不能再用了//{}中可以定义新类的属性和方法//此处的目的就是重写父类Thread的run()方法.@Overridepublic void run() {while(true){System.out.println("Thread run03");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}
};

这里的thread变量名指向的是新创建的Thread的匿名内部类(子类),而不是Thread类.

4.实现Runnable接口,重写run()方法,但使用匿名内部类:

Thread构造方法的参数,传了Runnable的匿名内部类的实例.

5.使用lambda表达式(推荐)

lambda表达式原理:

java">Thread thread=new Thread(()->{    //这里的()是形参列表,在这里,不需要传参数//()的前面应该有个函数名,这里是匿名的,所以没有名字//->后面的{}是方法体,while(true){System.out.println("Thread run5");try{Thread.sleep(1000);}catch(InterruptedException o){throw new RuntimeException(e);}}
});

这里的规则是方法不能脱离类单独存在.

这几种方法都是等价的,作用都相同.

Thread的构造方法

1.构造方法:

前两个在前面创建线程的时候都提到了,

第三,四个:给线程起个名字:

在jcolsole.exe中就能看到线程名字被修改

自己创建的线程默认是按照Thread-0 1 2 ...创建的,线程之间的名字可以重复,起名字是为了方便调试.

Thread的常用的属性:

1.ID:jvm自动分配的身份标识,不同线程不会重复

2.名称是调试的时候用到的

3.状态:

线程有不同的状态:就绪状态,阻塞状态

4.优先级:

优先级⾼的线程理论上来说更容易被调度到,线程的优先级在java中,效果不是很明显

5.是否后台线程:

和后台线程相对应的是前台线程,当一个进程开始运行的时候,只有前台线程都运行结束,后台线程才会结束.

JVM会在⼀个进程的所有⾮后台线程结束后,才会结束运⾏。

目前代码创建的线程都是前台线程,都会阻止线程的结束,当全部都执行完了,才会结束整个进程.

设置线程为后台线程:在start之前setDaemon(true);此时,该线程就为后台线程

在start之前,给thread线程设置成了后台线程,在main函数之后,休眠2秒,thread线程就执行了2秒,打印了两遍,main线程结束了,thread线程为后台线程,也就结束了.

6.是否存活:

表示内核中的线程是否还存活,在start之前,还没有开始线程,isAlive为false,

只有调用了start,线程才开始执行,isAive才为true.

2s之后,run()已经结束,isAlive为false.


http://www.ppmy.cn/embedded/147635.html

相关文章

利用git上传项目到GitHub

GitHub是基于git实现的代码托管。git是目前最好用的版本控制系统了,非常受欢迎,比之svn更好。 GitHub可以免费使用,并且快速稳定。 利用GitHub,你可以将项目存档,与其他人分享交流,并让其他开发者帮助你一…

lshw学习——简单介绍

文章目录 简介核心结构扫描设备原理scan_abiscan_burnerscan_cdromscan_cpufreqscan_cpuidscan_cpuinfoscan_device_treescan_diskscan_displayscan_dmiscan_fatscan_fbscan_graphicsscan_idescan_ideraidscan_inputscan_isapnpscan_lvmscan_memoryscan_mmcscan_mountsscan_net…

双剑合璧:转录组+宏基因组揭示微生物与宿主互作机制

微生物、宿主以及环境三者之间编织着一张错综复杂的生命网络,这张网的解析需要跨学科、多层面的信息协同。近日,《Lancet eBioMedicine》期刊上的一篇研究,采用多组学分析的独特视角,将皮肤微生物组、转录组等数据融会贯通&#x…

docker 安装 mongo 命令

## 拉取 MongoDB 镜像docker pull mongo:latest## 挂载文件目录:mkdir -p /usr/local/mongo/configmkdir -p /usr/local/mongo/datamkdir -p /usr/local/mongo/logstouch /usr/local/mongo/config/mongod.confchmod 777 /usr/local/mongo## 配置文件##vim …

网络视频监控平台/安防监控/视频综合管理Liveweb视频汇聚平台解决方案

一、当前现状分析 当前视频资源面临以下问题: 1)不同单位在视频平台建设中以所属领域为单位,设备品牌众多,存在的标准不一,各系统之间也没有统一标准; 2)各单位视频平台建设分散、统筹性差&am…

基于字节大模型的论文翻译(含免费源码)

基于字节大模型的论文翻译 源代码: 👏 star ✨ https://github.com/boots-coder/LLM-application 展示 项目简介 本项目是一个基于大语言模型(Large Language Model, LLM)的论文阅读与翻译辅助工具。它通过用户界面&#xff08…

【Mars3d】设置backgroundImage、map.scene.skyBox、backgroundImage来回切换

相关链接: http://mars3d.cn/editor-vue.html?keyex_1_2_1&idmap/other/backgroundImg 实现代码: export function show1() {map.setOptions({scene: {backgroundType: "image",backgroundImage: "url(//data.mars3d.cn/img/busin…

计算机视觉学习证书为智能化工作做贡献

在当今数字化与智能化浪潮汹涌澎湃的时代,计算机视觉技术作为人工智能领域的关键分支,正以前所未有的速度改变着我们的生活与工作方式。工信部计算机视觉证书,便是在这一背景下应运而生的权威认证,为广大技术爱好者与从业者开启了…