多线程学习总结

news/2024/11/17 23:52:46/文章来源:https://www.cnblogs.com/ZWJ7671277/p/18350106

Java 多线程学习总结

本章目标

  • 理解线程的基本概念
  • 理解线程与进程的区别
  • 熟悉线程的实现方式
  • 了解线程的管理
  • 熟悉线程的生命周期
  • 掌握线程同步
  • 掌握线程池
  • 了解线程通信
  • 掌握线程定时器

什么是进程

进程就是正在运行的程序,它是系统进行资源分配和调度的基本单位,各个进程之间相互独立,系统给每个进程分配不同的地址空间和资源

image-20210802095954225

Win 操作系统任务管理器查看应用程序运行的进程

什么是线程

线程就是程序(进程)执行的任务(分为单线程和多线程)

image-20210802100059707

进程与线程的区别

地址空间

进程之间是独立的地址空间,但同一进程的线程共享本进程的地址空间

资源占用

同一进程内的线程共享本进程的资源,如内存、I/O、CPU 等,但是进程之间的资源是独立的

健壮性

一个进程崩溃后不会对其他进程产生影响;一个线程崩溃则整个进程都死掉,所以多进程要比多线程更健壮

执行过程

进程可以独立执行,线程不能独立执行,线程必须依存于进程

并发与资源消耗

进程和线程都可以并发(同时)执行,但进程创建和切换消耗资源大,线程创建和切换消耗资源小

创建线程

方式一:继承 Thread 类,并重写 run( ) 方法
public class MyThread extends Thread {   public void run() {  for ( int i = 0; i < 10; i++ )  {  System.out.println(“子线程");  }  }  public static void main(String[] args) {  MyThread myThread = new MyThread(); myThread.start();  } 
}
方式二:实现 Runnable 接口,并实现 run( ) 方法
public class MyThread implements Runnable {   public void run() {  for ( int i = 0; i < 10; i++ )  {  System.out.println(“子线程");  }  }  public static void main(String[] args) {  Thread myThread = new Thread(new MyThread); myThread.start();  } 
}

线程的状态

当线程被创建并启动以后,它既不是一启动就进入了执行状态,也不是一直处于执行状态。在线程的生命周期中,它要经过新建(New)、就绪(Runnable)、运行(Running)、阻塞(Blocked)和死亡(Dead)5种状态。尤其是当线程启动以后,它不可能一直"霸占"着CPU独自运行,所以CPU需要在多条线程之间切换,于是线程状态也会多次在运行、阻塞之间切换。

  1. 新建状态:当程序使用new关键字创建了一个线程之后,该线程就处于新建状态,此时仅由JVM为其分配内存,并初始化其成员变量的值

  2. 就绪状态:当线程对象调用了start()方法之后,该线程处于就绪状态。Java虚拟机会为其创建方法调用栈和程序计数器,等待调度运行

  3. 运行状态:如果处于就绪状态的线程获得了CPU,开始执行run()方法的线程执行体,则该线程处于运行状态

  4. 阻塞状态:当处于运行状态的线程失去所占用资源之后,便进入阻塞状态

  5. 死亡状态:当线程的 run() 方法执行完成,线程正常结束或抛出一个未捕获的异常,也可以直接调用 stop() 方法结束线程(容易导致死锁,不推荐使用)

image-20210802100411740

线程暂停执行条件
  • 线程优先级比较低,不能获得 CPU 时间片
  • 使用 sleep( ) 方法使线程睡眠
  • 通过调用 wait( ) 方法,使线程处于等待状态
  • 通过调用 yield( ) 方法,线程主动出让 CPU 控制权
  • 线程由于等待一个I/O事件处于阻塞状态
线程优先级

Java 中线程优先级是在 Thread 类中定义的常量

  • NORM_PRIORITY : 值为 5

  • MAX_PRIORITY : 值为 10

  • MIN_PRIORITY : 值为 1

缺省优先级为 NORM_PRIORITY

修改和查看线程优先级方法

  • final void setPriority(int newPriority) //修改当前线程的优先级

  • final int getPriority()//查看当前线程的优先级

多线程

多线程并发问题

image-20210802100639790

线程 A 和线程 B 同时操作(读写)同一进程下的共享资源,这将导致数据不一致的问题,被称为多线程并发问题。

线程同步

多线程共享数据时,可能会发生数据不一致的情况,而线程同步就是为了解决多线程并发问题,它可以确保在任何时间点一个共享的资源只被一个线程使用

实现线程同步的三种方式

  • 使用同步代码块
  • 使用同步方法
  • 使用互斥锁 (更灵活的代码控制)
线程死锁

image-20210802101002998

线程 A 和线程 B 都想访问对方的资源,但都不愿意让对方先访问,这样谁也无法继续执行下去,这就是线程死锁(线程死锁很少发生,但一旦发生就很难调试)

线程池

如果并发的线程数量很多,并且线程执行一个时间很短的任务就结束了,这样就会频繁的创建和销毁线程,导致大大降低系统的运行效率

image-20210915140509073

线程池工作原理
  • 程序启动时向线程池中提前创建一批线程对象
  • 当需要执行任务时,从线程池中获取一个空闲的线程对象
  • 任务执行完毕后,不销毁线程对象,而是将其返还给线程池,并再次将状态设置为空闲
线程池优缺点
  • 减少频繁创建和销毁线程对象的时间消耗,提高了程序运行的性能(优点)
  • 线程池中空闲的线程对象,会占用系统更多的内存存储空间(缺点)

线程池是一种以时间换空间的性能优化策略

Java四种内置线程池

Java 语言提供了一系列线程池的实现,以解决实际开发中各种对线程池的需求

  • newCachedThreadPool
  • newFixedThreadPool
  • newScheduledThreadPool
  • newSingleThreadExecutor
Java 两个基础线程池

如果内置四个线程池实现仍无法满足需求,则 Java 语言还提供了两个基础线程池

  • ThreadPoolExecutor 类
  • ScheduledThreadPoolExecutor 类

这两个基础线程池用于用户创建自定义线程池,以获得更大的灵活度,同时开发难度也更大

线程间通信

wait-notify 机制

线程同步能够解决多线程并发问题,但它没有实现线程间的通信

image-20210802102246501

Java 提供了一个精心设计的线程间通信机制,使用wait()、notify() 和 notifyAll() 方法,这些方法是作为 Object 类中的 final 方法实现的。这三个方法仅在 synchronized 方法中才能被调用

  • wait() 方法:方法告知被调用的线程退出监视器并进入等待状态,直到其他线程进入相同的监视器并调用 notify( ) 方法
  • notify( ) 方法:通知同一对象上第一个调用 wait( )线程
  • notifyAll() 方法:通知调用 wait() 的所有线程,具有最高优先级的线程将先运行

线程定时器

Time 类

Timer是一个普通的类,其中有几个重要的方法

  • schedule() 方法:启动定时器一个定时任务
  • cancel()方法:终止定时器所有定时任务

启动一个定时任务就创建一个线程,线程会一直执行下去,直到调用终止定时任务

TimerTask 类

TimerTask 是一个抽象类,需要实现该类

  • run()方法:定时任务逻辑
//创建一个定时任务
Timer timer = new Timer();
timer.schedule(new TimerTask() {@Overridepublic void run() {// 任务执行代码}
}, 5000,1000); //延时 5s 每间隔1s 执行一次

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

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

相关文章

AOP -面向切面编程

AOP -面向切面编程 aop是oop(面向对象编程)的补充和完善。oop是一种纵向开发,然而当面对需要一些横向的功能如日志,就会导致大量重复的代码。 aop利用横切把一些重复的非核心的代码插入到核心代码周围,不需要重复写很多遍。 应用场景:日志记录,在方法的执行前后插入日志…

OneKeyAdmin 后台任意文件下载

无它唯手熟尔,还是太菜了侵权声明 本文章中的所有内容(包括但不限于文字、图像和其他媒体)仅供教育和参考目的。如果在本文章中使用了任何受版权保护的材料,我们满怀敬意地承认该内容的版权归原作者所有。 如果您是版权持有人,并且认为您的作品被侵犯,请通过以下方式与我…

适合新手进行接口与自动化测试练习的推荐网站!!!

对于新手来说,接口与自动化测试练习网站是提升技能的重要资源。以下是一些适合新手进行接口与自动化测试练习的推荐网站: 1、httpbin.org httpbin.org是一个在线提供HTTP服务的网站,它提供了丰富的HTTP接口,用于测试HTTP请求和响应的各种信息,如cookie、IP、headers和登录…

《最新出炉》系列小成篇-Python+Playwright自动化测试-67 - 模拟手机浏览器兼容性测试

1.简介 在日常工作中,我们会遇到需要使用不同的硬件设备测试兼容性的问题,尤其是现在手机型号基本上是每个厂家每年发布一款新机型,而且手机的屏幕大小分辨率五花八门的,我们基本不可能全部机型都用真机测试一遍,playwright提供了模仿机型的功能,我们可以使用playwright来…

在IIS上部署ASP.NET Core Web API和Blazor Wasm详细教程

前言 前段时间我们完成了七天.NET 8 操作 SQLite 入门到实战的开发系列教程,有不少同学留言问如何将项目发布部署到IIS上面运行。本篇文章我们就一起来讲讲在IIS上部署ASP.NET Core Web API和Blazor Wasm。 前提条件 安装.NET Core SDKhttps://dotnet.microsoft.com/zh-cn/dow…

Sublime Text 4 如何配置成完美的OI编辑器,优雅的打比赛

Sublime Text 完整配置编译文件点击新建编译系统(Tools -> Build system -> New build system)改为以下代码: Ubuntu : {"encoding": "utf-8","working_dir": "$file_path","shell_cmd": "g++ \"$file_name…

打造个性化Typora写作体验的必备插件

该文档为 typora_plugin 的 README 文档,为了方便国内的同学阅读而转载到本博客。该文档为 typora_plugin 的 README 文档,为了方便国内的同学阅读而转载到本博客。 原文地址:https://github.com/obgnail/typora_plugin 插件地址:可以去 GitHub 上下载,也可以在我的公众号…

使用蓝奏云备份大于一百兆的压缩包——分卷,手机

开源软件地址:Flut Renamer 1.分卷 2.更名 3.上传成功。

读零信任网络:在不可信网络中构建安全系统13运行时安全

读零信任网络:在不可信网络中构建安全系统13运行时安全1. 建立分发系统的信任 1.1. 分发是选择交付给下游使用者的工件的过程,构建系统会产生许多工件,其中一部分需要交付给下游使用者 1.2. 工件发布1.2.1. 在不改变工件内容的情况下指定一个工件作为权威发布版本的操作被称…

暑假模拟15

暑假模拟15 \(T_A\) 串串 简单字符串题,考虑枚举回文中心,哈希维护,没什么思维量,但是不好调。 wang54321 有高级 manacher 做法,大家快去膜拜她。 #include<bits/stdc++.h> using namespace std; #define ll long long const int N=1e6+100; const ll mod=10000010…

Kubernetes-Argo CD

Kubernetes高级工具Argo CD https://argo-cd.readthedocs.io/en/stable/ Argo CD 是针对 Kubernetes 的声明式 GitOps 持续交付工具。 Argo CD 是一个为 Kubernetes 而生的,遵循声明式 GitOps 理念的持续部署(CD)工具。 Argo CD 可在 Git 存储库更改时自动同步和部署应用程序…