首页 > 编程语言 >Java中多线程的学习

Java中多线程的学习

时间:2024-10-15 18:44:31浏览次数:8  
标签:Java 学习 线程 进程 run 多线程 方法

Java 多线程学习总结


目录

什么是进程

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

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

什么是线程

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

进程与线程的区别

地址空间

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

资源占用

同一进程内的线程共享本进程的资源,如内存、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() 方法结束线程(容易导致死锁,不推荐使用)

线程暂停执行条件
  • 线程优先级比较低,不能获得 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()//查看当前线程的优先级

多线程

多线程并发问题

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

线程同步

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

实现线程同步的三种方式

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

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

线程池

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

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

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

Java四种内置线程池

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

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

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

  • ThreadPoolExecutor 类
  • ScheduledThreadPoolExecutor 类

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

线程间通信

wait-notify 机制

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

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/BingBing-8888/p/18468157

相关文章

  • 四,Java面向对象
    Java面向对象:封装与构造方法笔记封装private关键字:概述:private是Java中的访问修饰符,用于隐藏类的内部细节,只通过公共方法(public)提供访问。特点:使用private修饰的成员变量或方法只能在同一个类内部访问,不能被类的外部直接访问。使用方式:成员变量:this.成员变量名,......
  • 大模型技术学习过程梳理
    “学习是一个从围观到宏观,从宏观到微观的一个过程”学习大模型技术也有几个月的时间了,之前的学习一直是东一榔头,西一棒槌,这学一点那学一点,虽然弄的乱七八糟,但对大模型技术也算有了一个初步的认识。因此,今天就来整体梳理一下大模型技术的框架,争取从大模型所涉及的理论,技......
  • 普通人学习大模型应该怎么学?
    前言近年来,人工智能领域掀起了一股“大模型”热潮,吸引了无数研究者和企业关注。所谓“大模型”,是指那些参数量巨大、结构复杂人工智能模型,如谷歌BERT、OpenAI的GPT等。这些模型在自然语言处理、计算机视觉等任务中取得了显著成果,引领着人工智能技术发展。那么,这些“大模型......
  • Python学习流水账Day5——有关Python中的函数
    文章目录前言一、Python中的函数1.内置函数2.定义一个函数调用函数为函数设置参数实参形参给函数设置多个形参默认形参函数的返回值函数的变量局部变量全局变量3.匿名函数4.递归函数总结前言简单的python复习第五天:不是用来教学的,上班没劲,主打一个本科毕业没竞......
  • 钓鱼学习
    一、邮件钓鱼通过最新时事展开钓鱼伪造系统升级场景钓鱼最新漏洞补丁更新通知钓鱼伪造公司服务器被攻击钓鱼模仿高职人员钓关键信息案例:https://www.freebuf.com/articles/es/321412.htmlhttps://www.secrss.com/articles/31208https://www.4hou.com/posts/z9yYhttps:......
  • 前端原型链:探索 JavaScript 中的继承奥秘
    一、引言在前端开发领域,JavaScript是一门广泛应用的编程语言。而原型链作为JavaScript中一个重要的概念,对于理解JavaScript的面向对象特性和实现继承机制起着关键作用。它不仅影响着代码的组织和复用方式,还决定了对象之间的关系和属性访问规则。本文将深入探讨前端原型链......
  • 讨论java有基础类型,为什么还要有封装类型呢?两者之间的比较方式?
    java有哪些基础类型boolean/1byte/8char/16short/16int/32float/32long/64double/64java为什么有基础类型,为什么还要有封装类型呢?举个例子吧,Character和char的区别是在于char只是存了个数据,而Character的区别在于他带有了一系列操作该数据的方法好处是什么呢?......
  • Java 初学 day 08
    java081、Abstract关键字java为了表示现实生活中抽象的概念集合,提供了一个关键字给我们使用:abstractabstract抽象的可以修饰类,修饰成员方法1.被abstract修饰的类是抽象类,抽象类不能被实例化2.被abstract修饰的方法是抽象方法,抽象方法不能有大括号实现3.在抽......
  • java 不建议使用stack
    Java不建议使用Stack的原因和替代方案在Java编程中,Stack类通常用于处理数据结构中的堆栈实现。然而,随着Java的发展,越来越多的开发者开始质疑是否应该继续使用Stack类。本文将探讨不建议使用Stack的原因,示例代码,以及推荐的替代方案。Stack类简介在Java中,Stack是一种后进先出(LIFO......
  • Java在for循环中修改集合
    前天看到一篇文章什么?for循环也会出问题?,里面涉及到在for循环中修改集合,想起来自己刚入行的时候就碰到过类似的问题,于是复现了一下文章中的问题,并试验了其它在循环中修改集合的方法。底层原理参考什么?for循环也会出问题?这篇文章的分析1.在fori中修改集合在fori中修改集合,不会......