首页 > 其他分享 >多线程学习总结

多线程学习总结

时间:2024-08-09 08:55:02浏览次数:12  
标签:总结 Java 学习 线程 进程 run 多线程 方法

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() {
    @Override
    public void run() {
        // 任务执行代码
    }
}, 5000,1000); //延时 5s 每间隔1s 执行一次

标签:总结,Java,学习,线程,进程,run,多线程,方法
From: https://www.cnblogs.com/ZWJ7671277/p/18350106

相关文章

  • 哪种编程语言更适合学习数据结构和算法:C++、Java 还是 Python?
    作为一名工程专业的学生,​​我正在尝试决定使用哪种编程语言来学习数据结构和算法(DSA)。我正在考虑C++,它提供高性能和强大的标准模板库,但对于初学者来说可能很复杂。Java具有强大的语法和内置集合,使DSA概念更容易掌握,尽管我不确定它与C++相比的性能。Python以其简单性和......
  • 联邦学习综述性论文
    ClientSelectioninFederatedLearning:Principles,Challenges,andOpportunities一、摘要大量的工作旨在解决FL训练的不同方面,如优化聚合方法[7],[8],增强隐私保护[9],[10]和改进鲁棒性[11]。一个有效的FL客户端选择方案可以显著提高模型的准确性[16],增强公平性[24],增强鲁棒......
  • 2024-8-8 算法学习
    P1972[SDOI2009]HH的项链题意:统计区间内不同数字的种类对于[l,r]区间内的某一种贝壳来说,只有最右边的贝壳有意义,所以将所有询问区间[l,r]按照r从小到大排序;对每一个数字记录上一次出现的位置利用线段树完成单点添加和区间查询P3567[POI2014]KUR-Couriers题意:统计区间内出......
  • 易漏范数总结(二范数、F范数以及其他变种范数)
    一.矩阵二范数矩阵的二范数是一个值,具体计算如下:                                                即矩阵的二范数是通过计算其最大特征值并进行开根号得到的。二.向量二范数向量的二范数也是一个值,不过是对向量的每个......
  • Java入门学习——Day01初识Java
    一、为什么学习Java1.1Java历史1.1.1背景介绍        Java语言最初由SunMicrosystems的詹姆斯·高斯林(JamesGosling)等人在1991年开始开发,当时SunMicrosystems希望开发一种能够在各种消费电子设备上运行的小型程序语言,最初命名为Oak。        1995年5月......
  • 开关电源设计学习笔记
    在学习开关电源设计之前,我们应该思考一下学习的初心和目标,初心是能在你想要放弃的时候坚持下去的动力,目标是怎样才能算完成了对于硬件的认识和学习,是对于学习成果的检验。我们所学的知识想要转化为技能和能力都需要在实践中进行的,所以,在学习中我们的目标设立在运用所学知识设......
  • 深度学习中,图像和文本的输入区别
    图像输入1.数据预处理尺寸调整(Resizing):将图像调整到统一的尺寸,如224×224或256×256。归一化(Normalization):对每个像素值进行归一化,像素值通常归一化到[0,1]或[-1,1]范围。数据增强(DataAugmentation):包括随机裁剪、翻转、旋转等操作,以增加模型的泛化能力......
  • typeScript学习之环境搭建
    ^_^--今天来介绍一下运行typeScript代码需要的环境------->    下面是需要安装的软件和环境以及安装过程中遇到的问题,win10、win11系统下载最新或者稳定版的软件就可以,因为我使用的是win7系统,很多软件不支持或对win7系统的版本不再维护,尝试了很多次找到合适的对应版本一......
  • C语言学习笔记 Day8(函数)
    Day8 内容梳理:目录Chapter6 函数6.0概述6.1 定义函数6.2 调用函数(1)实参&形参(2)调用无参函数(3)调用有参函数6.3 声明函数6.4 终止函数(exit&return)6.5多文件编程(1)设置主文件(2)创建头文件(3)导入头文件Chapter6 函数6.0概述函数的分类(2种):   ......
  • 机器学习是怎么回事?
    什么是机器学习最近在入门人工智能,发现了一大堆的名词,和大家分享一下我是怎么理解机器学习的。机器学习的概念在百度上有定义,这里我说一下我自己的定义哈。机器学习就是让机器可以猜到你心里想的那个数字。我们想一下,什么是学习?不就是从一开始的瞎猜到合理的推测吗?我们玩一......