高级进阶多线程——多任务处理、线程状态(生命周期)、三种创建多线程的方式

这篇具有很好参考价值的文章主要介绍了高级进阶多线程——多任务处理、线程状态(生命周期)、三种创建多线程的方式。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Java多线程

Java中的多线程是一个同时执行多个线程的进程。线程是一个轻量级的子进程,是最小的处理单元。多进程和多线程都用于实现多任务处理。

但是,一般使用多线程而不是多进程,这是因为线程使用共享内存区域。它们不分配单独的内存区域以节省内存,并且线程之间的上下文切换比进程花费的时间更少。

Java多线程主要用于游戏,动画等。

优点

(1)它不会阻塞用户,因为线程是独立的,可以同时执行多个操作。
(2)可以一起执行许多操作,因此可以节省时间。
(3)线程是独立的,因此如果在单个线程中发生异常,它不会影响其他线程。

多任务处理

多任务处理是同时执行多个任务的过程。使用多任务来利用CPU,多任务处理可以通过两种方式实现:

基于进程的多任务处理(多进程)
基于线程的多任务处理(多线程)

基于进程的多任务处理(多进程)
  • 每个进程在内存中都有一个地址。 换句话说,每个进程分配一个单独的内存区域。
  • 进程是重量级的。
  • 进程之间的通信成本很高。
  • 从一个进程切换到另一个进程需要一些时间来保存和加载寄存器,内存映射,更新列表等。
基于线程的多任务处理(多线程)
  • 线程共享相同的地址空间。
  • 线程是轻量级的。
  • 线程之间的通信成本很低。

注意:一次只执行一个线程。

线程的生命周期(线程状态)

线程可以处于五种状态之一。 根据sun解释,线程生命周期在java中有以下几种状态:初始(NEW)运行(RUNNABLE)阻塞(BLOCKED)等待(WAITING)超时等待(TIMED_WAITING)终止(TERMINATED)

java中线程的生命周期由JVM控制,java线程状态如下:

  1. 初始(NEW):新创建了一个线程对象,但还没有调用start()方法。
  2. 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。
    线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。
  3. 阻塞(BLOCKED):表示线程阻塞于锁。
  4. 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
  5. 超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。
  6. 终止(TERMINATED):表示该线程已经执行完毕。
新建状态:

使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。

就绪状态

当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。

运行状态

如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。

阻塞状态:

如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:

  • 等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。

  • 同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。

  • 其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。

死亡状态

一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。

创建线程

创建一个线程有三种方法:

  • 通过扩展Thread类。
  • 通过实现Runnable接口。
  • 通过 Callable 和 Future 创建线程。

Thread类
Thread类提供了在线程上创建和执行操作的构造函数和方法。Thread类扩展了Object类并实现了Runnable接口。

常用的Thread类构造函数

  • Thread()
  • Thread(String name)
  • Thread(Runnable r)
  • Thread(Runnable r,String name)

Thread类的常用方法:

  • public void run(): 用于执行线程的操作。
  • public void start(): 开始执行线程,JVM调用线程上的run()方法。
  • public void sleep(long miliseconds): 使当前正在执行的线程休眠(暂时停止执行)达指定的毫秒数。
  • public void join(): 等待线程死亡。
  • public void join(long miliseconds): 按指定的毫秒数等待线程死亡。
  • public int getPriority(): 返回线程的优先级。
  • public int setPriority(int priority): 更改线程的优先级。
  • public String getName(): 返回线程的名称。
  • public void setName(String name): 更改线程的名称。
  • public int getId():返回线程的编号(ID)。
  • public Thread.State getState(): 返回线程的状态。
  • public boolean isAlive(): 测试线程是否处于活动状态。
  • public void yield(): 使当前正在执行的线程对象暂时暂停并允许其他线程执行。
  • public void suspend(): 用于挂起线程(depricated)。
  • public void resume(): 用于恢复挂起的线程(depricated)。
  • public void stop(): 用于停止线程(depricated)。
  • public boolean isDaemon(): 测试该线程是否为守护进程线程。
  • public void setDaemon(boolean b): 将线程标记为守护进程或用户线程。
  • public void interrupt(): 中断线程。
  • public boolean isInterrupted(): 测试线程是否被中断。
  • public static boolean interrupted(): 测试当前线程是否已被中断。

Runnable接口:
Runnable接口应由任何其实例由线程执行类实现。Runnable接口只有一个run()方法。

  • public void run(): 用于执行线程的操作。

启动线程:

Thread类的start()方法用于启动新创建的线程。它执行以下任务:

  • 一个新线程启动(使用新的callstack)。
  • 线程从New状态移动到Runnable状态。
  • 当线程有机会执行时,它的目标run()方法将运行。

示例

1. 通过扩展Thread类线程示例
package com.yiibai;

class Multi extends Thread {
    public void run() {
        System.out.println("thread is running...");
    }

    public static void main(String args[]) {
        Multi t1 = new Multi();
        t1.start();
    }
}

执行上面示例代码,得到以下结果:

thread is running...
2. 通过实现Runnable接口的线程示例
package com.yiibai;

class Multi implements Runnable {
    public void run() {
        System.out.println("thread is running...");
    }

    public static void main(String args[]) {
        Multi m1 = new Multi();
        Thread t1 = new Thread(m1);
        t1.start();
    }
}

执行上面示例代码,得到以下结果:

thread is running...

如果没有扩展Thread类,类对象就不会被视为一个线程对象。所以需要明确地创建Thread类对象。传递实现Runnable类的对象,以便类的run()方法可以执行。

3.通过 Callable 和 Future 创建线程
  • 创建 Callable 接口的实现类,并实现 call() 方法,该 call() 方法将作为线程执行体,并且有返回值。
  • 创建 Callable 实现类的示例,使用 FutureTask 类来包装 Callable 对象,该 FutureTask 对象封装了该 Callable 对象的 call() 方法的返回值。
  • 使用 FutureTask 对象作为 Thread 对象的 target 创建并启动新线程。
  • 调用 FutureTask 对象的 get() 方法来获得子线程执行结束后的返回值。
public class Zeus implements Callable<Integer> {
    public static void main(String[] args)  
    {  
        CallableThreadTest ctt = new CallableThreadTest();  
        FutureTask<Integer> ft = new FutureTask<>(ctt);  
        for(int i = 0;i < 100;i++)  
        {  
            System.out.println(Thread.currentThread().getName()+" 的循环变量i的值"+i);  
            if(i==20)  
            {  
                new Thread(ft,"有返回值的线程").start();  
            }  
        }  
        try  
        {  
            System.out.println("子线程的返回值:"+ft.get());  
        } catch (InterruptedException e)  
        {  
            e.printStackTrace();  
        } catch (ExecutionException e)  
        {  
            e.printStackTrace();  
        }  
  
    }
    @Override  
    public Integer call() throws Exception  
    {  
        int i = 0;  
        for(;i<100;i++)  
        {  
            System.out.println(Thread.currentThread().getName()+" "+i);  
        }  
        return i;  
    }  
}

创建线程的三种方式的对比

  •  采用实现 Runnable、Callable 接口的方式创建多线程时,线程类只是实现了 Runnable 接口或 Callable 接口,还可以继承其他类。
  • 使用继承 Thread 类的方式创建多线程时,编写简单,如果需要访问当前线程,则无需使用 Thread.currentThread() 方法,直接使用 this 即可获得当前线程。

线程的几个主要概念

在多线程编程时,你需要了解以下几个概念:

  • 线程同步

  • 线程间通信

  • 线程死锁

Java线程调度程序

Java的线程调度程序是JVM的一部分,它决定应该运行哪个线程。无法保证线程调度程序将选择运行哪个可运行线程。

一次只能有一个线程在一个进程中运行。线程调度程序主要使用抢占式或时间切片调度来调度线程。

抢占式调度与时间分片的区别

在抢占式调度下,优先级最高的任务一直执行,直到它进入等待或死亡状态或更高优先级的任务出现。 在时间切片下,任务执行预定义的一段时间,然后重新进入就绪任务池。 然后,调度程序根据优先级和其他因素确定接下来应执行的任务。文章来源地址https://www.toymoban.com/news/detail-643826.html

到了这里,关于高级进阶多线程——多任务处理、线程状态(生命周期)、三种创建多线程的方式的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • MediaPlayer状态图及生命周期

    MediaPlayer状态图及生命周期 MediaPlayer是Android中的uoge多媒体播放类,我们能通过它控制音视频流或本地音视频资源的播放过程。 这一片博客主要介绍MediaPlayer状态图及生命周期。先看一张官网很经典的MediaPlayer状态机的图片。 其中椭圆代表MediaPlayer驻留状态,弧代表播放器控制

    2023年04月08日
    浏览(35)
  • Java线程生命周期详解

    Java中的线程生命周期是多线程开发的核心概念。了解线程的生命周期以及它们如何进行状态转换对于编写有效且无错误的多线程程序至关重要。 Java线程主要有以下几个状态,这些状态定义在Thread.State枚举类中: 新建状态(New) :当我们创建一个新的线程实例时,线程就处

    2024年02月11日
    浏览(40)
  • HarmonyOS Stage模型 UIAbility生命周期状态

    UIAbility的生命周期包括Create、Foreground、Background、Destroy四个状态 Create 状态,在UIAbility实例 创建 时触发,对应onCreate回调。可以在onCreate回调中进行相关初始化操作 Foreground 状态,在UIAbility 切换至前台 时触发。对应onForeground回调,在UIAbility的UI页面可见之前,即UIAbility切换至

    2024年01月16日
    浏览(50)
  • Spring进阶(十六)之spring生命周期

    目录 Bean生命周期 阶段1:Bean元信息配置阶段 Bean信息定义4种方式 API的方式 XML的方式 properties文件的方式 注解的方式 小结 阶段2:Bean元信息解析阶段 Bean元信息的解析主要有3种方式 XML方式解析:XmlBeanDefinitionReader properties文件定义bean的解析: PropertiesBeanDefinitionReader 注解方式

    2024年02月03日
    浏览(41)
  • Flutter 05 组件状态、生命周期、数据传递(共享)、Key

    1、Widget组件生命周期 和其他的视图框架比如android的Activity一样,flutter中的视图Widget也存在生命周期,生命周期的回调函数体现在了State上面。组件State的生命周期整理如下图所示: createState: 当一个StatefulWidget插入到渲染树结构、或者从渲染树结构移除时,都会调用Stateful

    2024年02月05日
    浏览(53)
  • Flutter笔记:Flutter的应用生命周期状态(lifecycleState)管理

    Flutter笔记 Flutter的应用生命周期状态(lifecycleState)管理 作者 : 李俊才 (jcLee95):https://blog.csdn.net/qq_28550263 邮箱 : 291148484@163.com 本文地址 :https://blog.csdn.net/qq_28550263/article/details/134127670 【介绍】: WidgetsBinding.instance 是Flutter中用于管理应用程序事件和生命周期的重要工具

    2024年02月06日
    浏览(45)
  • 【JavaEE进阶】Bean 作用域和生命周期

    注意在此例子中需要用到lombok lombok是什么? Lombok 是一个 Java 库,它通过注解的方式来简化 Java 代码的编写。它提供了一组注解,让我们可以通过在代码中添加这些注解来自动生成样板式的代码,如 getter、setter、构造函数、toString 等。 使用 Lombok 可以有效地减少冗余的样板代

    2024年02月12日
    浏览(48)
  • K8s进阶之路-Pod的生命周期

    Pod创建过程: 首先创建一个pod,然后创建一个API Server 和 Etcd【把创建出来的信息存储在etcd中】 然后创建 Scheduler,监控API Server是否有新的Pod,如果有的话,会通过调度算法,把pod调度某个node上 在node节点,会通过 kubelet -- apiserver 读取etcd 拿到分配在当前node节点上的pod,然后

    2024年02月20日
    浏览(49)
  • Angular 17+ 高级教程 – Component 组件 の 生命周期钩子 (Lifecycle Hooks)

    之前在 Component 组件 の Angular Component vs Custom Elements 文章中,我们有学习过几个基础的 Lifecycle Hooks。 比如 OnChanges、OnInit、AfterViewInit、OnDestroy,但那篇只是微微带过而已。 这篇让我们来深入理解 Angular 的 Lifecycle Hooks。   在 Component 组件 の Dependency Injection NodeInjector 文章中

    2024年03月09日
    浏览(51)
  • unity的C#学习——多线程编程(线程的生命周期、创建与管理)与线程相关类

    多线程编程是 C# 一个比较难且涵盖面比较广的知识点,本文整理仓促而且属于笔记向博客,有些地方必然还存在不严谨和错误,本人会在日后的使用过程中不断完善。如果发现问题或有改进意见可以在评论区提出,我会及时修改。 线程是程序的执行流程,也被称为 轻量级进

    2024年02月12日
    浏览(45)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包