【JavaEE初阶】多线程(1)

2024-09-07 14:36
文章标签 java 多线程 初阶 ee

本文主要是介绍【JavaEE初阶】多线程(1),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

欢迎关注个人主页:逸狼


创造不易,可以点点赞吗~

如有错误,欢迎指出~



目录

并发编程 

线程 与 进程

创建线程

写法1 

写法2

写法3

写法4

写法5

Thread类的常见构造方法

前台/后台 线程


并发编程 

并发编程: 通过写特殊的代码 把多个cpu的核心都利用起来 

多进程编程就是一种典型的并发编程 ,但多进程编程最大的问题是 进程太'重'了(创建进程/销毁进程,时间/空间开销比较大,一旦需求场景需要频繁的创建销毁进程 ,开销就非常明显了(最典型的就是 服务器开发(针对每个发送请求的客户端,都需要创建一个单独的进程,由这个进程负责给客户端提供服务)))

线程 与 进程

为解决进程开销比较大的问题,发明了'线程'(可以理解为更轻量化的进程,也能解决 并发编程的问题,创建/销毁的开销要比进程更低,因此多线程的编程就成为了当下最主流的并发编程方式(通过多线程可以充分利用好多核cpu))

 进程在系统中是通过PCB这样的 数据结构来 描述 的,通过链表的形式来 组织 的, 线程同样也是通过PCB来描述的(一个进程,是一组PCB,一个线程,是一个PCB,存在包含关系:一个进程中,可以包含多个线程)

  • 进程是系统  "资源分配" 的基本单位
  • 线程是系统  "调度执行" 的基本单位

一个可执行程序,运行的时候,操作系统就会创建进程,给这个程序分配各种系统资源(cpu,内存,硬盘,网络带宽....),同时也会在这个进程中创建一个或多个 线程,这些线程再去cpu上执行.

  • 一个进程要么包含一个,要么包含多个 线程,不能没有
  • 同一个进程中的这些线程 ,共用同一份系统资源

线程比进程 更轻量化 主要在于 创建线程省去了"分配资源" 的过程,销毁线程 也省去了'释放资源'的过程 (一旦创建进程,同时也会创建第一个线程--->负责分配资源 ,创建后面的线程就不必分配资源了)  

随着线程数目的增加,每个线程要负责完成的工作量就变少了,这些线程同时开始工作,总的消耗时间会进一步减少, 但是如果线程的数目太多,超出了 cpu核心数目,此时就无法再完成所有线程的"并发"执行.势必会存在严重的 '竞争'

  • 多个线程之间 ,可能会相互影响,线程安全问题,一个线程一旦抛出异常,也可能会把其他线程也一起带走.
  • 多个进程之间, 一般不会相互影响,一个进程崩溃了,不会影响其他进程(进程的 隔离性)

创建线程

class MyThread extends Thread{//Thread类可以直接使用,不用导入任何包//重写run方法public void run(){System.out.println("hello thread");}
}public class Demo1 {public static void main(String[] args) {MyThread t =new MyThread();//创建线程t.start();//调用start就会再进程内部创建一个新的线程,新的线程就会执行刚才run里的代码}
}

注意:上述代码中,run方法并没有手动去调用, 但这个方法最终执行了,此时这样的方法称为'回调函数' 

这个代码运行起来 是一个进程,但这个进程中包含两个进程,主线程 和新线程 ,这两个线程并发/ 并行的在cpu上执行

写法1 

继承Tread ,重写run,通过start 实例启动线程

class MyThread extends Thread{//Thread类可以直接使用,不用导入任何包//重写run方法public void run(){while(true){System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}public class Demo1 {public static void main(String[] args)  {MyThread t =new MyThread();//创建线程t.start();//调用start就会再进程内部创建一个新的线程,新的线程就会执行刚才run里的代码while(true){System.out.println("hello main");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}

写法2

 实现Runnable ,重写run,通过Thread的实例,把Runnable的实例传进去,再调用start

class MyRunnable implements Runnable{@Overridepublic void run() {//描述线程要完成的逻辑是啥while(true){System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}
}
public class Demo2 {public static void main(String[] args) throws InterruptedException {MyRunnable runnable= new MyRunnable();Thread t =new Thread(runnable);t.start();while(true){System.out.println("hello main");Thread.sleep(1000);}}
}

Runnable 是用来描述 要执行的任务是什么,通过 Thread创建线程,线程要执行的任务是通过Runnable来描述的,而不是通过Thread自己来描述的, 这里的runnable只是一个任务,并不是和'线程'这样的概念强相关,后续执行这个任务的载体,可以是线程,也可以是其他....(有利于代码的 解耦合)

写法3

继承Thread,重写run ,通过 匿名内部类来实现,本质上是写法1

package thread;public class Demo3 {public static void main(String[] args) throws InterruptedException {Thread t = new Thread() {@Overridepublic void run() {while (true) {System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}};t.start();while (true) {System.out.println("hello main");Thread.sleep(1000);}}
}

写法4

通过匿名内部类实现 本质上是写法2

public class Demo4 {public static void main(String[] args) throws InterruptedException {Thread t= new Thread(new Runnable() {@Overridepublic void run() {while(true){System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}});t.start();while(true){System.out.println("hello main");Thread.sleep(1000);}}
}

写法5

基于 lambda 表达式来创建线程(很多时候,写"匿名内部类"的目的不是为了写"类"而是为了写类里面的方法,lambda就是直接能够表示要写的run方法)

public class Demo5 {public static void main(String[] args) throws InterruptedException {Thread t=new Thread(()->{while(true){System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}});t.start();while(true){System.out.println("hello main");Thread.sleep(1000);}}
}

Thread类的常见构造方法

ThreadGroup线程组 :把多个线程放到一组中,方便统一设置线程的一些属性, 现在很少使用线程组,线程的相关属性用的也不多,现在更多的会使用 线程池.

属性中的 ID和 状态是JVM自动分配的,不能手动设置

线程的状态有 阻塞和就绪

设置不同的优先级 会影响到系统的调度(基于'统计'规则的影响,肉眼很难观察到)

前台/后台 线程

  • 前台线程:  某个线程在执行的过程中,够阻止进程的结束
  • 后台线程:  某个线程在执行的过程中,不能阻止进程的结束(进程结束时会带走正在执行的后台线程)

一个进程中,前台线程可以有多个(创建的线程默认就是前台的),必须所有前台线程都结束,进程才结束

代码中常见的new Thread 对象,生命周期和内核中实际的线程 是不一定一样的,可能会出现Thread对象仍然存在,但是内核中的线程不存在的这样的情况(但不会出现Thread对象不存在,线程还存在 的这次情况)

调用start 之前,内核中还没有创建线程

线程的run执行完毕,内核的线程就无了,但Thread对象仍然存在

这篇关于【JavaEE初阶】多线程(1)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1145327

相关文章

Java中StopWatch的使用示例详解

《Java中StopWatch的使用示例详解》stopWatch是org.springframework.util包下的一个工具类,使用它可直观的输出代码执行耗时,以及执行时间百分比,这篇文章主要介绍... 目录stopWatch 是org.springframework.util 包下的一个工具类,使用它

Java进行文件格式校验的方案详解

《Java进行文件格式校验的方案详解》这篇文章主要为大家详细介绍了Java中进行文件格式校验的相关方案,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、背景异常现象原因排查用户的无心之过二、解决方案Magandroidic Number判断主流检测库对比Tika的使用区分zip

Java实现时间与字符串互相转换详解

《Java实现时间与字符串互相转换详解》这篇文章主要为大家详细介绍了Java中实现时间与字符串互相转换的相关方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、日期格式化为字符串(一)使用预定义格式(二)自定义格式二、字符串解析为日期(一)解析ISO格式字符串(二)解析自定义

Java使用Curator进行ZooKeeper操作的详细教程

《Java使用Curator进行ZooKeeper操作的详细教程》ApacheCurator是一个基于ZooKeeper的Java客户端库,它极大地简化了使用ZooKeeper的开发工作,在分布式系统... 目录1、简述2、核心功能2.1 CuratorFramework2.2 Recipes3、示例实践3

Springboot处理跨域的实现方式(附Demo)

《Springboot处理跨域的实现方式(附Demo)》:本文主要介绍Springboot处理跨域的实现方式(附Demo),具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不... 目录Springboot处理跨域的方式1. 基本知识2. @CrossOrigin3. 全局跨域设置4.

springboot security使用jwt认证方式

《springbootsecurity使用jwt认证方式》:本文主要介绍springbootsecurity使用jwt认证方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地... 目录前言代码示例依赖定义mapper定义用户信息的实体beansecurity相关的类提供登录接口测试提供一

Spring Boot 3.4.3 基于 Spring WebFlux 实现 SSE 功能(代码示例)

《SpringBoot3.4.3基于SpringWebFlux实现SSE功能(代码示例)》SpringBoot3.4.3结合SpringWebFlux实现SSE功能,为实时数据推送提供... 目录1. SSE 简介1.1 什么是 SSE?1.2 SSE 的优点1.3 适用场景2. Spring WebFlu

基于SpringBoot实现文件秒传功能

《基于SpringBoot实现文件秒传功能》在开发Web应用时,文件上传是一个常见需求,然而,当用户需要上传大文件或相同文件多次时,会造成带宽浪费和服务器存储冗余,此时可以使用文件秒传技术通过识别重复... 目录前言文件秒传原理代码实现1. 创建项目基础结构2. 创建上传存储代码3. 创建Result类4.

Java利用JSONPath操作JSON数据的技术指南

《Java利用JSONPath操作JSON数据的技术指南》JSONPath是一种强大的工具,用于查询和操作JSON数据,类似于SQL的语法,它为处理复杂的JSON数据结构提供了简单且高效... 目录1、简述2、什么是 jsONPath?3、Java 示例3.1 基本查询3.2 过滤查询3.3 递归搜索3.4

Tomcat版本与Java版本的关系及说明

《Tomcat版本与Java版本的关系及说明》:本文主要介绍Tomcat版本与Java版本的关系及说明,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Tomcat版本与Java版本的关系Tomcat历史版本对应的Java版本Tomcat支持哪些版本的pythonJ