java中的线程如何理解——精简

Java中的 “线程“ 指两个或多个事件在同一个时间段内发生。指两个或多个事件在同一时刻发生(同时发生)。在操作系统中,安装了多个程序,并发指的是在一段时间内宏观上有多个程序同时运行,这在单 CPU 系统中,每一时刻只能有一道程序执行,即微观上这些程序是分时的交替运行,只不过是给人的感觉是同时运行,那是因为分时交替运行的时间是非常短的。而在多个 CPU 系统中,则这些可以并发执行的程序便可以分配到多个处理器上(CPU),实现多任务并行执行,即利用每个处理器来处理一个可以并发执行的程序,这样多个程序便可以同时执行。 阅读详情

目录

方式一:继承Thread类 

方式二: 实现Runnable接口

方式三:实现Callable接口 

Thread获取和设置线程名称 

Thread类的线程休眠方法 

引言

经过前面的学习,我们已经了解到了IO流的知识,那么今天我们就将要开始学习Java中的线程,首先我们应该理解“线程”是什么意思?线程(thread)是一个程序内部的一条执行路径,我们所熟悉的main方法其实就是一条单独执行路径,若程序中只有一条执行路径那么这个程序就是 单线程程序 ;既然有单线程,那么也相对的会有多线程,字面意思可以理解为“相对单线程从软硬件上多条执行流程的技术”,多线程的好处是 提高CPU的利用率 。 在多线程程序中,一个线程必须等待的时候,CPU可以运行其它的线程而不是等待,大大提高程序的效率。好了,废话不多说开始今天的学习吧!

多线程的创建

方式一:继承Thread类

方式一创建过程:

  1. 定义一个子类MyThread继承线程类java.lang.Thread,重写run()方法;
  2. 创建MyThread类的对象;
  3. 调用线程对象的start()方法启动线程(启动后仍然执行run()方法); 

    public class ThreadDemo01 {
        public static void main(String[] args) {
            MyThread myThread1 = new MyThread();
            myThread1.start();
            for (int i = 0; i < 3; i++) {
                System.out.println("主线程正在执行~~");
            }
        }
    }
    class MyThread extends Thread{
        @Override
        public void run() {
            for (int i = 0; i < 3; i++) {
                System.out.println("子线程正在执行~~");
            }
    
        }
    }
    //输出结果(不唯一):
    //主线程正在执行~~
    //主线程正在执行~~
    //主线程正在执行~~
    //子线程正在执行~~
    //子线程正在执行~~
    //子线程正在执行~~

    在以上代码中共有两个线程在执行,分别是main方法的主线程和线程对象mythread调用start()启动的子线程。不过输出结果为什么会不唯一的呢?原因是因为两个线程在执行过程中会发生CPU的抢占,谁先抢到谁将优先执行。

那么我们为什么不直接使用线程对象调用run()方法呢?若直接调用run()则只是普通的调用方法,即单线程,而start()方法则是用来启动的子线程的,由此才能出现多线程。

方式一优缺点:

  • 优点: 编码简单;
  • 缺点: 线程类已经继承Thread,无法继承其他类,不利于扩展; 

方式二: 实现Runnable接口

方式二创建过程:

1、定义一个线程任务类MyRunnable实现Runnable接口,重写run()方法;

2、创建MyRunnable对象;

3、把MyRunnable任务对象交给Thread处理;

4、调用线程对象的start()方法启动线程;

Thread构造器方法
public Thread (String name)可以为当前线程指定名称
public Thread (Runnable target)封装Runnable对象成为线程对象
public Thread (Runnable target ,String name)封装Runnable对象成为线程对象,并指定线程名称
public class ThreadDemo02 {
    public static void main(String[] args) {
        MyRunnable target = new MyRunnable();
        Thread thread = new Thread(target);
        thread.start();
        for (int i = 0; i < 3; i++) {
            System.out.println("主线程正在执行~~");
        }
    }
}
class MyRunnable implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            System.out.println("子线程正在执行~~");
        }

    }
}
//输出结果(不唯一):
//主线程正在执行~~
//子线程正在执行~~
//子线程正在执行~~
//子线程正在执行~~
//主线程正在执行~~
//主线程正在执行~~

该代码与方式一的不同之处在于需要将MyRunnable任务对象封装在Thread中,其他的地方是基本上是没有变化的。

方式二优缺点:

优点: 线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强;

缺点: 编程多一层对象包装,如果线程有执行结果是不可以直接返回的。

接下来我们同样使用 实现Runnable接口(匿名内部类形式) 来实现多线程的创建:

1、创建Runnable匿名内部类对象;

2、交给Thread处理;

3、调用线程对象的start()启动线程;

//正常版:
public class ThreadDemo01 {
    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 3; i++) {
                    System.out.println("子线程正在执行~~");
                }
            }
        });
        thread.start();
        for (int i = 0; i < 3; i++) {
            System.out.println("主线程正在执行~~");
        }
    }
}

//lambda简化版:
new Thread(()-> {
                for (int i = 0; i < 3; i++) {
                    System.out.println("子线程正在执行~~");
                }
        }).start();

该种方法从本质上其实并没有太大的区别只不过是一个需要创建线程对象,而另一个则是通过匿名内部类实现的多线程。并且该块代码也可以通过lambda表达式进行精简,不知道大家是否还对这个知识点有印象呢?若忘记了可以看一下这篇文章: Java中的lambda表达式如何理解——精简

方式三:实现Callable接口

在学习过前面两种创建多线程的方式以后,我们会发现存在一个问题:1、重写的run()方法不能直接返回结果;2、不适合需要返回线程执行结果的业务场景。因此,我们需要第三种方式来解决这些问题。

方式三创建过程:

1、定义类实现Callable接口,重写call()方法,封装要做的事情;

2、用FutureTask把Callable对象封装成线程任务对象;

3、把线程任务对象交给Thread处理;

4、调用Thread的start()方法启动线程,执行任务;

5、线程执行完毕后,通过FutureTask的get()方法获取任务执行的结果。

方法名称说明
public FutureTask<>(Callable call)把Callable对象封装成FutureTask对象
public V get() throws Exception获取线程执行call方法返回的结果
public class ThreadDemo03 {
    public static void main(String[] args) throws Exception {
        MyCallable myCallable = new MyCallable();
        FutureTask<String> futureTask = new FutureTask<>(myCallable);
        Thread thread = new Thread(futureTask);
        thread.start();
        int sum= 0;
        for (int i = 0; i < 3; i++) {
            sum+=i;
        }
        System.out.println(sum);
        String s =futureTask.get();
        System.out.println(s);
    }
}
class MyCallable implements Callable<String > {
    @Override
    public String call(){
        int sum=0;
        for (int i = 0; i < 3; i++) {
            sum+=i;
        }
        return "子线程计算结果:"+sum;
    }
}
//输出结果:
//3
//子线程计算结果:3

方式三优缺点:

优点:

线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强;

可以在线程执行完毕后去获取 线程执行的结果;

缺点:

编码复杂一点;

总结

方式优点缺点
继承Thread类编程比较简单,可以直接使用Thread类中的方法扩展性较差,不能再继承其他的类,不能返回线程执行的结果
实现Runnable接口扩展性强,实现该接口的同时还可以继承其他的类编程相对复杂,不能返回线程执行的结果
实现Callable接口扩展性强,实现该接口的同时还可以继承其他的类,可以得到线程的执行结果编程相对复杂

常用方法

Thread获取和设置线程名称

方法名称说明
String getName()获取当前线程的名称,默认线程名称是Thread-索引
void setName(String name)

将此线程更改为指定的名称,通过构造器也可以设置线程名称

简单地通过一段代码让大家能够清晰地了解这个代码该如何使用:

public class ThreadDemo04 {
    public static void main(String[] args) throws Exception {
        thread thread1 = new thread();
        thread1.setName("1号子线程");
        thread1.start();
        thread thread2 = new thread();
        thread2.setName("2号子线程");
        thread2.start();
    }
}
class thread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 3; i++) {
            System.out.println(this.getName()+"正在执行任务"+i);
        }
    }
}
//输出结果:
//2号子线程正在执行任务0
//1号子线程正在执行任务0
//2号子线程正在执行任务1
//1号子线程正在执行任务1
//2号子线程正在执行任务2
//1号子线程正在执行任务2

Thread类的线程休眠方法

方法名称说明
public static void sleep(long time)让当前线程休眠指定的时间后再继续执行,单位为毫秒
public class ThreadDemo05 {
    public static void main(String[] args) throws Exception {
        for (int i = 0; i < 5; i++) {
            System.out.println(i);
            if (i==3){
                Thread.sleep(5000);
            }
        }
    }
}
//输出结果:
//1
//2
//3
//在输出过3以后,等待5秒之后再进行输出
//4
一篇文章彻底弄懂java中的线程池,如何理解JAVA中的线程池 java、线程池、Executor 阅读详情

相关推荐

Java中的多线程详解(超级简单理解)(下篇)

下篇来了噢,虽晚但到,感兴趣的可以继续观看

a15766649633的博客 1340

Java线程属性详解

本节来介绍下Java中线程的属性,即线程的编号(ID)、名称(Name)、守护线程(Daemon)、优先级(Priority),讲解下这些属性各自的作用,以及开发中需要注意的事项。其实除了线程名称属性,其他属性在编码过程中,是无需人为指定的。线程的ID、优先级和守护线程更多的是用作只读属性使用,并不需要手动修改默认配置。

五道口 837

保姆级教程:在RK3588 Android12设备树(DTS)中配置MIPI 8 Lane双通道与DSC显示

本文详细介绍了在RK3588 Android12平台上配置MIPI 8 Lane双通道与DSC显示的实战指南。通过设备树(DTS)参数详解、DSC参数计算与PPS配置、双通道同步机制实现等内容,帮助开发者高效完成高分辨率屏幕驱动配置,解决嵌入式显示系统开发中的常见挑战。

weixin_30905133的博客 399

std::thread线程命名

也可以参考我另外一篇文章,另外一篇更详细些。为线程设置名字的最大的好处是在程序出错时,它会出现在 GDB 的出错信息里,可以更快地定位问题。有两种方法可以给线程设置名字:一种在线程的调用函数内部设置,还有一种是在外部对指定线程变量做设置。

jinking01的专栏 3810

BPMN-JS :修改节点“Change Type”事件类型

修改路径:node_modules\bpmn-js\lib\features\replace\ReplaceOptions.js。

TaylorY的博客 680

泄露测试仪CTS的Sentinel I28使用

本文介绍:泄露测试仪CTS的Sentinel I28使用

qq_34047402的博客 2206

创建线程池的正确姿势,请给它指定一个有意义的名字

为什么我们创建线程或者线程池的时候,需要指定有意义的线程名称? 最终目的是为了方便回溯。 我们在日常开发中,一个项目中会创建很多个线程池用来资源隔离,但是如果我们没有一个好的命名的话,出问题的时候就会难以定位。 public class Demo5 { ​ public static void main( String[] args ) throws IOException { new Thread(()->{ System.out.println(&q

qianlia的博客 4837

ESP32-S3双模CMSIS-DAP调试器:USB+WiFi无线调试方案

CMSIS-DAP是ARM生态中标准化的嵌入式调试协议接口,广泛用于Keil、IAR、STM32CubeIDE等开发环境。其核心原理是通过SWD/JTAG物理层实现目标芯片寄存器访问、内存读写与断点控制,依赖确定性时序和低延迟通信。传统DAPLink调试器受限于USB线缆束缚,而WiFi-USB-DAPLink项目将完整CMSIS-DAP v2协议栈移植至ESP32-S3平台,同时支持USB CDC直连与WiFi TCP远程通道,兼顾实时性与网络化部署能力。该方案无需主机驱动、兼容主流IDE,并支持多机并发

weixin_31185473的博客 372

Java中的线程基础篇-线程基本概念

Java中的线程一、基础知识1. 进程、线程、协程1.1 进程1.2 线程1.3 协程2. 串行、并发、并行2.1 串行2.2 并发2.3 并行二、线程的创建1. 继承Thread类1.1 实现步骤1.2 特点2. 实现Runnable接口2.1 实现步骤2.2 与Thread相比3. 实现Callable接口(JDK5.0新增)3.1 实现步骤3.2 与Runnable接口相比三、线程的常用方法四、线程的生命周期1. 基本概念2. 六个状态 一、基础知识 1. 进程、线程、协程 1.1 进程 基本概念

weixin_44446626的博客 2343

Windows加域迁移避坑指南:Profwiz工具实战中的5个常见问题与解决方案

本文详细解析了使用Profwiz工具进行Windows加域迁移时的5个常见问题及解决方案,包括临时配置文件生成、密码策略冲突、SID冲突等。通过实战案例和优化技巧,帮助IT运维团队高效完成账户配置文件迁移,确保Active Directory环境下的数据完整性和权限无缝衔接。

q9r0s的博客 525

21天教你学会PCIe专栏(17)--多功能设备

1.1 定义多功能PCIe设备:多功能PCIe设备是指在一个物理设备中集成了多种功能的设备。这些功能可以通过不同的PCIe功能(Function)来实现,每个功能可以独立配置和管理。1.2 优点资源利用率:通过集成多种功能,减少物理设备的数量,提高资源利用率。成本效益:减少硬件成本和功耗,提高系统的经济性。灵活性:用户可以根据需要启用或禁用不同的功能,提高系统的灵活性。可扩展性:通过增加新的功能,扩展设备的功能,提高系统的可扩展性。1.3 应用场景网络设备。

xiaoheshang_123的博客 531

并发编程:Java线程的本质

线程1. 创建一个线程类1.1 点击start方法2. linux的线程控制原语2.1 centos安装man手册2.2 查看pthread_create函数定义3. 结论 1. 创建一个线程类 可以正常运行 1.1 点击start方法 start方法内有一个start0方法,而且start0方法是一个native本地方法。是通过JNI调用的系统方法,这个start0方法对应的系统创建线程的方法是pthread_create。 2. linux的线程控制原语 2.1 centos安装man手册

Fisher3652的博客 644

观测器选择与工程实践建议

摘要:永磁同步电机(PMSM)无传感器控制中,观测器选型需综合考虑应用场景、性能需求与成本。消费级(家电、工具)推荐滑模观测器(SMO),成本低、鲁棒性强;工业级(伺服、泵阀)适用扩展卡尔曼滤波器(EKF),精度高但计算复杂;车规级(EPS、主驱动)需混合观测器(SMO+EKF),兼顾全速域性能与可靠性。低速时需高频注入法,IPMSM更适用。SMO易实现但存在抖振,EKF调试复杂。未来趋势是混合架构与AI增强,提升适应性与性能。选型需权衡速度范围、电机类型、处理器能力及成本。

汽车软件开发 146

Java中的多线程如何理解——精简

通过前面的学习,我们已经学会了线程是如何创建的以及线程的常用方法,接下来呢,我们将要深入性了解线程中的知识,主要是线程安全,线程同步,线程池三个知识点。我相信大家通过这节课的简单地学习,就可以大概地掌握了线程吧!好了,废话不多说,我们开始今天的学习吧!......

weixin_50635856的博客 4632

使用SSC添加大量的SDO条目

使用SSC添加大量的SDO条目 SSC用表格添加SDO,PDO部分必须指定到0x1600和0x1A00分配TxPdo和RxPdo映射,在0x1C12和0x1C13分别分配到SM2和SM3。在0x6000和0x7000未指定的entry就是SDO部分。

PI_sunyang的博客 3172

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

如何精简的理解Java中的多线程

分为线程池处理Runnable任务,线程池处理Callable任务和Executors的工具类构建线程池对象,我们将要深入性了解线程中的知识,主要是线程安全,线程同步,线程池三个知识点。

Java_ttcd的博客 132

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

最精简的java 线程池与任务队列,帮助理解概念

 import java.util.*; public class WorkQueue {    private final int nThreads;//线程池的大小    private final PoolWorker[] threads;//用数组实现线程池    private final LinkedList queue;//任务队列   public WorkQueue(int nT

清澈反省 2184

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

java线程池的构造方法_Java中对线程池构造方法ThreadPoolExecutor机理的简单理解(精简)...

话不多说奔主题,精神抖擞就是干!1. 所在包:java.util.concurrent2. 源码片段publicThreadPoolExecutor(intcorePoolSize,intmaximumPoolSize,longkeepAliveTime, TimeUnitunit, BlockingQueueworkQueue,ThreadFactorythreadFactory...

weixin_39847437的博客 64

Java中的网络编程如何理解——精简

经过前面的课程,我们已经大概地了解到多线程的知识了,不知道大家是否已经掌握了呢?如果已经掌握了的话,那么我们今天就开始学习Java中的网络编程的相关知识,那么什么是网络编程呢?网络编程是可以让程序与网络上的其他设备中的数据进行数据交互。常见的通信模式有两种形式:Client-Server(CS)、Browser/Server(BS)。接下来我们将要学习的知识是网络通信的三要素、UDP通信、TCP通信。......

weixin_50635856的博客 1916

【JAVA-Day78】深入理解Java中的线程同步机制

哎呀呀,作为一名Java博主,我今天要和大家深入探讨一下Java中的线程同步机制啦!线程同步可不是闹着玩的,它是用来控制多个线程之间的访问顺序和共享资源的安全性的哦!在这篇博客中,我会带领大家从什么是线程同步开始,一直到线程同步的应用场景和面试题,最后进行总结,希望大家能够有所收获哟~线程同步是一种重要的机制,用来保证多个线程在访问共享资源时的安全性。在多线程环境下,如果多个线程同时访问共享资源,并且其中至少一个线程会对资源进行写操作,就有可能出现数据不一致的情况。

沉淀所学,分享所思,让热爱与成长同行。商务记录AI实战经验,助力开发者快速成长。 热爱AI,希望做出有影响力的技术成果。 技术点亮生活,分享连接价值与机会。 专注AI落地实战,陪你走好技术每一步。 3万+

理解 Java 中的多线程编程

多线程编程是 Java 开发中的一项重要技能,能够显著提高程序的性能和响应性。本文从基础概念入手,详细讲解了 Java 中的多线程实现方式、线程同步与通信、线程池、并发集合以及死锁与活锁的避免方法,并通过实际案例加深理解。希望本文能够帮助新手朋友全面掌握 Java 多线程编程,提升开发技能。

这家伙很懒,什么都没有留下 1058

Java基础——深入理解Java中的多线程(超级详细,值得你看)

Java中多线程,深入理解

haust_允谦的博客 4194

理解Java中的线程池和线程安全

1.背景介绍 Java中的线程池和线程安全是两个非常重要的概念,它们在多线程编程中发挥着至关重要的作用。线程池是一种资源管理机制,它可以有效地管理和重复利用线程,从而提高程序的性能和效率。线程安全则是指一个程序或系统在多线程环境下能够正确地访问和修改共享资源,从而避免数据竞争和其他线程相关的问题。 在本文中,我们将深入探讨Java中的线程池和线程安全,包括它们的核心概念、算法原理、具体操作步骤...

AI天才研究院 1009

Java中的线程

Java中的线程 1. 引入 1.1. 进程和线程 进程: 是正在运行的程序。比如在Windows系统中,一个运行的exe就是一个进程。 是系统进行资源分配和调度的独立单位 每一个进程都有它自己的内存空间和系统资源 线程: 是进程中的单个顺序控制流,是一条执行的路径。 线程总是属于某个进程,线程没有自己的虚拟地址空间,与进程内的其他线程一起共享分配给该进程的所有资源。 是CPU调度和分派的最小单位。 一个程序至少有一个进程,一个进程至少有一个线程。 1.2. 单线程和多线程 单线程:

Eternal_Summer 1767
上一篇: 追随云原生的Java-笔记
下一篇: Java 中的异常处理机制
JavaMonsterr
博客等级 码龄4年 211粉丝 481原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值