Java并发编程(一):了解Thread

【JAVA】50. 并发编程设计模式:Worker Thread与Thread - Per - Message Worker Thread 模式也称为线程池模式,它预先创建一组线程(工作线程),这些线程不断地从任务队列中取出任务并执行。当有新任务到来时,将任务放入任务队列,工作线程会自动从队列中取出任务进行处理。这种模式可以避免频繁创建和销毁线程带来的开销,提高系统的性能和资源利用率。Thread - Per - Message 模式是指为每个请求创建一个新的线程来处理。当有新的请求到来时,立即创建一个新的线程来执行该请求的处理逻辑。这种模式的优点是实现简单,每个请求的处理是独立的,不会相互影响; 阅读详情

1 引言

线程是进程中可独立执行的最小单位,也是CPU资源分配的基本单位。

线程的四个基本属性:

属性描述
编号id线程的唯一标识
名称线程的名字,默认“Thread-编号id”,可自定义
类别分为守护线程和用户线程,可以通过setDaemon(true)设置为守护线程
优先级表示希望哪个线程优先执行,Java中优先级取值范围是1~10,默认5

2 Java线程对象Thread常用的方法

1 start()

表示启动线程,让CPU调度器调度开启线程持行run()方法。而直接调用run()方法只是运行当前run方法,不会开启线程。

附上源码:

public synchronized void start() {
      
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
              
            }
        }
    }

    private native void start0();

通过源码,不难发现start()方法实际上是调用start0()方法启动线程的,而start0()是native方法。

简单说下native的原理及实现机制:

native修饰的表示本地方法,一个Native Method就是一个java调用非java代码(如C代码)的接口,Java中的Native Method并不提供实现体。

当一个类第一次被使用到时,这个类的字节码会被加载到内存,并且只会会被载一次。在这个被加载的字节码的入口维持着一个该类所有方法描述符的list,这些方法描述符包含这样一些信息:方法代码存于何处,它有哪些参数,方法的描述符(public之类)等等。

如果一个方法描述符内有native,这个描述符块将有一个指向该方法的实现的指针。这些实现在一些DLL文件内,但是它们会被操作系统加载到Java程序的本地方法栈。当一个带有本地方法的类被加载时,其相关的DLL并未被加载,因此指向方法实现的指针并不会被设置。只有当本地方法被调用时,这些DLL才会被加载,这是通过调用java.system.loadLibrary()实现的。

此外,不可不说的是,本地方法意味着和平台有关,因此使用了native的程序可移植性都不太高,并且本地方法是有开销的,它丧失了Java的很多优势。

2 sleep()

线程暂停阻塞等待一段时间,时间过了就继续。该方法是不释放锁的。

附源码:

public static native void sleep(long millis) throws InterruptedException

同样的,sleep()也是本地方法,底层也是通过C代码调用操作系统实现的

3 yield()

t.yield()表示t线程主动让出CPU执行权进入就绪态,所有线程重新争抢CPU(可能出现又是t线程抢到CPU执行权)。

附源码:

public static native void yield();

4 join()

t2线程正在运行,这时在t2线程中调用 t1.join() ,这是让线程t2等待线程t1执行结束再运行。

此方法可以让线程按顺序持行。自己线程中调用自己的join()方法是无实际意义的。

附源码:

 public final void join() throws InterruptedException {
       join(0);
   }
   
   public final synchronized void join(long millis)
   throws InterruptedException {
       long base = System.currentTimeMillis();
       long now = 0;

       if (millis < 0) {
           throw new IllegalArgumentException("timeout value is negative");
       }

       if (millis == 0) {
           while (isAlive()) {
               wait(0);
           }
       } else {
           while (isAlive()) {
               long delay = millis - now;
               if (delay <= 0) {
                   break;
               }
               wait(delay);
               now = System.currentTimeMillis() - base;
           }
       }
   }

join(long timeout)方法底层调用的是Object类的wait(long timeout)方法。

public final native void wait(long timeout) throws InterruptedException;

Object类的wait()方法是释放锁的。

3 Java线程运行状态

在这里插入图片描述
过程分析:

  1. new 的状态(NEW)

  2. start() 之后线程到达就绪状态等待CPU调度,CPU调度了 就是运行状态。(RUNNABLE)

  3. 调用了 TImedWaiting 就回到就绪状态,结束之后自动到运行状态(TIMED_WAITING)

  4. 调用 Waiting 就绪然后持行相应的方法到运行(WAITING)

  5. 调用 Blocked 等待进入同步代码快的锁。(BLOCKED)

  6. 结束状态Teminated(TERMINATED)

线程被挂起:正在CPU中调度的线程,CPU把该线程丢出去,持行其他线程,这就是线程被挂起。之后又回来持续该线程。(每个CPU每次只能持行一个线程)

4 Java线程调度原理

我们知道,在任意时刻,操作系统的CPU 只能执行一条机器指令,并且每个线程只有获取到 CPU 的使用权后,才可以执行指令(也就是说在任意时刻,只有一个线程占用 CPU,处于运行的状态)。
多线程并发运行实际上是指多个线程轮流获取 CPU 使用权,分别执行各自的任务。
线程的调度由 JVM 负责。
线程调度模型分为两类:时间片轮转调度模型和抢占式调度模型。JVM采用的是抢占式调度模型。

  • 时间片轮转调度模型

时间片轮转调度模型是让所有线程轮流获取 CPU 使用权,并且为每个线程分配相同的占用 CPU 的时间片,时间片用完了则线程自动放弃CPU。

  • 抢占式调度模型

JVM 采用的是抢占式调度模型,根据优先级来选择占用CPU,优先级越高线程被持行的几率就越大,如果线程的优先级都一样,那就随机选择一个线程,并让该线程占用 CPU。也就是如果我们同时启动多个线程,并不能保证它们能轮流获取到均等的时间片。
如果我们的程序想干预线程的调度过程,最简单的办法就是给每个线程设定一个优先级。

5 线程创建的四种方式

5.1 继承Thread类创建线程
/**
 * @author Carson
 * @date 2020/4/3 10:44
 */
public class MyThread {
    public static void main(String[] args) {
        new ThreadGenerator().start();
    }
}

class ThreadGenerator extends Thread {
    @Override
    public void run() {
        System.out.println("Starting thread>>>>>>>>>>>>>>>>>>>>>>");
    }
}

该方式的优缺点在于:

  • 优点:编写简单
  • 缺点:线程类已经继承了Thread,不能再继承别的类。
5.2 实现Runnable接口创建线程
/**
 * @author Carson
 * @date 2020/4/3 10:44
 */
public class MyThread {
    public static void main(String[] args) {
        new Thread(new ThreadGenerator()).start();
    }
}

class ThreadGenerator implements Runnable {
    @Override
    public void run() {
        System.out.println("Starting thread>>>>>>>>>>>>>>>>>>>>>>");
    }
}

当然,在使用Java8及更高版本时,可以直接使用Lambda表达式创建:

/**
 * @author Carson
 * @date 2020/4/3 11:22
 */
public class MyThread {
    public static void main(String[] args) throws Exception {
        new Thread(() -> {
            System.out.println("Starting thread>>>>>>>>>>>>>>>>>>>>>>");
        }).start();
    }
}
5.3 使用Callable和Future创建线程
/**
 * @author Carson
 * @date 2020/4/3 10:44
 */
public class MyThread {
    public static void main(String[] args) throws Exception {
        ThreadGenerator threadGenerator = new ThreadGenerator();
        FutureTask futureTask = new FutureTask(threadGenerator);
        new Thread(futureTask).start();
    }
}

class ThreadGenerator implements Callable {
    @Override
    public Object call() throws Exception {
        System.out.println("Starting thread>>>>>>>>>>>>>>>>>>>>>>");
        return true;
    }
}

同样的,也可以直接使用Lambda表达式创建:

/**
 * @author Carson
 * @date 2020/4/3 11:22
 */
public class MyThread {
    public static void main(String[] args) {
        FutureTask<Boolean> futureTask = new FutureTask<>(() -> {
            System.out.println("Starting thread>>>>>>>>>>>>>>>>>>>>>>");
            return true;
        });
        new Thread(futureTask).start();
    }
}

实现Callable接口和实现Runnable接口的不同点在于:

  • call()方法可以有返回值
  • call()方法可以声明并抛出异常
5.4 使用线程池,例如用Executor框架
/**
 * @author Carson
 * @date 2020/4/3 11:22
 */
public class MyThread {
    public static void main(String[] args) {
        ExecutorService executorService = Executors.newFixedThreadPool(6);
        /* execute方法不关心返回值。 */
        executorService.execute(new ThreadGenerator());
        /* submit方法有返回值-->Future */
        executorService.submit(new ThreadGenerator());
    }
}

class ThreadGenerator implements Runnable {
    @Override
    public void run() {
        System.out.println("Starting thread>>>>>>>>>>>>>>>>>>>>>>");
    }
}

在开发中推荐使用线程池的方式,用线程池管理线程既高效风险也较低。

点点关注,不会迷路

腾讯架构师理解的并发编程基石——Thread类的工作原理 1. 开篇词 说到并发编程,可能大家脑海中的第一印象会是 Thread、多线程、JUC、线程池、ThreadLocal 等等内容。确实,并发编程是 Java 编程中不可或缺的一部分,掌握并发编程的核心技术,在求职面试中会是摧城拔寨的利器。而今天将要跟大家一起聊聊的是:并发编程的基石——Thread 类的工作原理。 事实上,在笔者回忆关于 Thread 类的核心 API 以及对应的线程状态转换关系时,总觉得印象有一些模糊,故此才有这篇文章。本文的核心议题是 Thread 类,由此延伸出诸多议题,例如:进程 阅读详情

相关推荐

Java并发编程基础篇(一)之线程

前言 并发编程的目的是为了让程序运行得更快,但是,并不是启动更多的线程就能让程序最 大限度地并发执行。在进行并发编程时,如果希望通过多线程执行任务让程序运行得更快,会 面临非常多的挑战,比如上下文切换的问题、死锁的问题,以及受限于硬件和软件的资源限制问题。这一块内容也是面试核心考点之一,所以博主将以线程为起点,从0到1一起与小伙伴们走去Java并发编程之路上走一遭! 正文 进程?线程?傻傻分不清? 何谓进程 进程通常是程序、应用的同义词。进程的本质是一个正在执行的程序,程序运行时系统会创建一个进程,并且给每

weixin_48013460的博客 2686

Java里Thread的快捷使用方式

Java里Thread的快捷使用方式一、使用 Runnable 接口二、使用 Thread匿名类三、自定义 Thread子类 一、使用 Runnable 接口 new Thread(new Runnable() { @Override public void run() { //要运行的代码 } }).start(); 二、使用 Thread匿名类 new Thread(){ @Override

baihuolandi的博客 398

从Chimera到ChimeraX:科研绘图升级指南,让你的论文配图更专业

本文详细介绍了从UCSF Chimera升级到ChimeraX的科研绘图指南,帮助研究者提升论文配图质量。ChimeraX在渲染引擎、大分子处理能力和动画功能上具有显著优势,特别适合生命科学和结构生物学领域。文章涵盖材质设置、专业配色、工作流程和期刊适配等核心技巧,助力产出出版级分子可视化图像。

weixin_33670786的博客 933

Java并发编程(二):Thread与Runnable的底层原理

本篇是Java并发编程系列第二章,本章主要讲解Thread类实现的底层原理,Runnable接口的存在意义。以及Thread底层源码的原理深度剖析,值得一阅

FNTP_ 1662

IB网络下不同租户业务隔离方案

IB(InfiniBand)网络隔离可以在不同的通信模式下实现,其中包括 IPoIB(IP over InfiniBand)通信模式。在 IPoIB 模式下,InfiniBand 网络可以承载 IP 数据包,使得基于 IP 的应用程序能够在 InfiniBand 网络上进行通信。在这种情况下,IB 网络隔离通常指通过配置 Partition Key(PKey)来实现不同的租户或应用程序之间的网络隔离。然而,IB 网络隔离并不仅限于 IPoIB 模式。

guganly的专栏 1527

疾病负担研究(GBD)——如何使用joinpoint软件计算AAPC

疾病负担研究(GBD)——如何使用joinpoint软件计算AAPC

weixin_44240228的博客 1万+

Java并发编程:Thread核心知识解析

在当今的软件开发领域,尤其是在处理高并发、大数据量的应用场景中,如何有效地利用系统资源,提高程序的执行效率,成为了一个关键问题。一个典型的场景是,在一个在线交易系统中,用户请求的处理需要同时进行数据库操作、业务逻辑处理和结果反馈。如果这些操作是串行执行的,那么系统的响应速度将大大降低,用户体验也会大打折扣。为了解决这个问题,引入并发编程技术成为了一种必然选择。并发编程的核心在于能够让多个任务同时执行,从而提高程序的执行效率。然而,并发编程并非易事,它涉及到复杂的线程管理、资源共享和同步问题。

JavaCodePro的博客 1221

FEniCS学习笔记01:centos7下通过conda安装FEniCSx0.7

2023年版本的Fenicsx0.7,官网推荐使用conda命令安装集成好的Python包,因此我们的安装思路是先安装Anaconda,再按照官网步骤安装Fenics。

huahua_xiao的博客 5056

并发编程-Thread

要想研究并发编程首先得了解线程、进程、CPU他们三个之间的联系可以简单的理解为 一个进程里边包含多个线程,进程代表的就是电脑上启动的软件,统一都是由cpu通过切换时间片来进行调度。再举个例子,进程就好比一个工厂里的生产线,它有生产任务。线程就好比生产线上的工人,它们一起协作才能完成生产任务。每个工人(线程)干的活也不一样。那cpu就像老板,将不同的工序分配给不同的工人。总的来说通过合理地组织进程和线程的分工,并充分利用CPU的计算能力,可以有效地提高计算机的处理效率。

heqishengcai201s的博客 911

AI测试入门:如何测试AI对话模型/智能体?「详细介绍」

作为测试人员,我们需要掌握特定的技能和方法来有效地测试这些复杂的AI对话模型和智能体。传统的软件测试方法在这里可能不再完全适用,我们需要开发新的测试策略和技术来应对AI系统的独特特性。在这篇文章中,我们将深入探讨如何测试AI对话模型和智能体。

blues_C的博客 6859

(十五)CX20106A 中超声波测量的应用

(十五)CX20106A 中超声波测量的应用

m0_52555663的博客 4511

Java并发编程一 多线程

Java并发编程一 多线程Java并发编程是一个很热点的话题,无论在面试时候还是在高并发的场景中。都会涉及到Java的并发编程相关的知识。Java的并发编程有两个主要的基础知识,一个是线程安全另一个是线程间通信。 摘要 1,线程概念 2,Java线程的实现方式 3,Java线程状态流转介绍 4,Thread类中的常用方法分析

刘越洋子 2634

YOLOv11与Roboflow数据预处理实战:从原始数据到高性能模型

摘要 Roboflow平台与YOLOv11的结合为计算机视觉开发者提供了高效的工作流。Roboflow提供数据集管理、预处理、增强和导出的一站式解决方案,支持多种标注格式并与YOLOv11无缝集成。YOLOv11在YOLO系列基础上进行了架构创新,包括深度宽度优化、C3k2机制和C2PSA注意力机制,提供从纳米版到超大版的多种模型变体。 使用Roboflow的流程包括:注册工作区、收集/导入数据(支持本地和公开数据集)、专业标注(含SAM辅助)、预处理(尺寸调整、归一化等)和数据增强(几何变换和颜色调整)。

本博客聚焦 YOLOv11 全流程落地,涵盖架构优化、数据集处理、训练技巧与多场景部署,兼及国产数据库、Java 开发与 AI 模型应用,内容兼顾理论与工程实践,为开发者提供系统干货,助力高效提升技术能力。 350

Java并发编程:Thread.java源码解析

Java Thread源码解析 1.前言   我们知道,new一个thread,调用它的start的方法,就可以创建一个线程,并且启动该线程,然后执行该线程需要执行的业务逻辑,那么run方法是怎么被执行的呢? 2.正文 2.1.Thread源码解析 先看如下例子。 @Test public void test03() throws InterruptedException { ...

【Mr-Coolerwu】 533

越野换了逐飞的ips200pro的屏幕后代码烧录中报错: “Cannot initialize device connection” 和 “Flashing failed” ...如何解决?

🏆 本文收录于《全栈Bug调优(实战版)》专栏,致力于分享我在项目实战过程中遇到的各类Bug及其原因,并提供切实有效的解决方案。无论你是初学者还是经验丰富的开发者,本文将为你指引出一条更高效的Bug修复之路,助你早日登顶,迈向财富自由的梦想🚀!同时,欢迎大家关注、收藏、订阅本专栏,更多精彩内容正在持续更新中。让我们一起进步,Up!Up!Up!    备注: 部分问题/难题源自互联网,经过精心筛选和整理,结合数位十多年大厂实战经验资深大佬经验总结所得,数条可行方案供所需之人参考。

**My Coding Family** 1150

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

Java并发编程(一)Thread详解

根据上面的内容,我们已经系统的学习Thread的使用了,然而学而不思则罔,最后留一个思考题:根据本文介绍的知识,怎么能避免死锁?(哈哈,卖个关子,根据文章的知识点组合可以得出答案)

2501_92669908的博客 852

计算机控制技术及应用

《计算机控制技术及应用》通过总结作者的科研成果和吸收国内外的先进理论、方法和技术,以计算机控制系统的网络化、开放化、智能化和集成化发展趋势为主线索,主要介绍计算机控制系统的基本概念和计算机控制系统的典型形式,计算机控制系统的数学描述与基本分析方法,以及数字PID控制器、最少拍控制系统、达林算法、状态变量设计法等设计方法及其各种改进算法。重点突出计算机控制系统输入输出通道接口的设计方法和典型控制系统的设计案例与实现方法等。

Java多线程:常见的线程的创建方法及Thread类详解

线程是程序的执行流程的最小单元,一个进程(程序的执行实例)可以由一个或多个线程组成,每个线程都有自己的执行路径和执行状态。线程可以并发执行,即多个线程可以同时在不同的处理器核心或计算机上运行,从而提高程序的运行效率。线程与进程的区别在于,进程是操作系统对一个正在运行的程序的抽象,而线程是进程内部的一个执行单位。一个进程可以有多个线程,这些线程共享进程的资源,如内存空间、文件描述符等。线程之间可以通过共享内存的方式进行通信,相比于进程间通信(如管道、消息队列)的开销更小。

luming的博客 1652

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Java并发编程:Thread类的使用

Java并发编程:Thread类的使用 Java并发编程:Thread类的使用   在前面2篇文章分别讲到了线程和进程的由来、以及如何在Java中怎么创建线程和进程。今天我们来学习一下Thread类,在学习Thread类之前,先介绍与线程相关知识:线程的几种状态、上下文切换,然后接着介绍Thread类中的方法的具体使用。   以下是本文的目录大纲:   一.线程的状态   二.上下文切换...

yizhizou123ABC的专栏 204

如何学习Java并发编程

2012年我刚转行到互联网,那年夏天我从传统通信行业跳槽到互联网行业。那是我成年后看的第一部国产动画片,可谓惊为天人。里面有所谓的八奇技,其中有一门绝技称为:术之尽头,炁体源流。虽然目前作者还没有揭开谜底,但从定义上来说,炁体源流大概有“追本溯源,回归本质”的含义。为什么扯这些呢?很多人学不好Java并发编程,恰恰是因为没有抓住本质。

smart_an的专栏 1485

Java并发编程实战(一)

xxx系列文章 xxxx系列(1)― xxxx系列(2)― xxxxx系列(3)― 提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录xxx系列文章前言一、一级标题1二、一级标题21.二级标题总结 前言 晚上刷视频刷到河北王校长的bug排除视频,校长深厚的基本功令我汗颜,需要好好学习一下多线程的相关知识了,由此开了这个系列,以极客专栏的学习为主,记下笔记,辅以processon画流程图,尽可能提高自己的并发编程水平 参考链接: 一、一级标题1   Java 里 sync

qq_40662424的博客 1543

Java并发编程之Thread知识整理

Java并发编程之线程知识

u010569015的博客 2057

Java并发编程理解02:线程的启动(Thread, Runnable, Callable, Future and FutureTask)

本文学习了java线程的实现原理、线程的启动详情,从Thread到Runnable,再到Callable, Future和FutureTask等,每一步都从原理到实战代码一步到位,最后还附有大厂爱问面试题供大家理解消化~。

three_131的博客 765

JAVA并发编程(一)并发编程线程基础

JAVA并发编程(一)并发编程线程基础1.1什么是线程?1.2线程的创建与运行1.2.1继承Thread类创建并运行线程1.2.2实现Runnable接口创建并运行线程1.2.3使用FutureTask创建并运行线程1.2.4小结1.3线程的状态转换 1.1什么是线程?       在讲什么是线程之前,我要提一个概念,那就是进程。那么什么...

qq_43080270的博客 531

Java并发编程(一) 并发编程基础

Java并发编程并发编程基础一、 进程和线程1. 进程2. 线程3. 进程与线程的区别:二、Java多线程编程1. Thread和Runnable1)实现Runnable接口2)继承Thread类并重写run方法3)匿名内部类3. Java中的线程状态4. Java中的线程状态转换5. 线程通信1)等待/通知2)管道输入/输出流3)Thread.join()4)ThreadLocal 并发编程基础...

qq_35017434的博客 861
上一篇: 高并发下接口幂等性解决方案
下一篇: Java并发编程(二):LockSupport应用及原理分析
少侠露飞
博客等级 码龄9年 214粉丝 117原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值