Java多线程新手指南:从零开始学习多线程创建,有两下子!

  咦咦咦,各位小可爱,我是你们的好伙伴 bug菌,今天又来给大家手把手教学Java SE系列知识点啦,赶紧出来哇,别躲起来啊,听我讲干货记得点点赞,赞多了我就更有动力讲得更欢哦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~


🏆本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!

环境说明:Windows 10 + IntelliJ IDEA 2021.3.2 + Jdk 1.8

前言

  多线程已是众人眼里老生常谈的话题之一了,在日常项目开发中它也是最为熟知且常用的技术之一,毕竟它能够允许程序同时执行多个任务,从而提高程序的响应速度和资源利用率,顾名思义,就是让计算机的多个核心同时工作,就像多个人同时做不同的任务一样。

  但在Java这种流行的编程语言中,多线程的使用尤为重要,因为它能帮助我们写出更高效、更流畅的程序,毕竟Java作为一种广泛应用于开发领域的语言,提供了强大的多线程支持,也提供了丰富的多线程支持,使得开发者可以轻松地实现并发编程。所以今天我继续来聊聊它,本文将重点介绍及演示如何使用Java来创建多线程,及衍生穿插知识点,带着大家能零基础轻松入门多线程编辑。

  而在前两期中,我也着重的讲解了多线程相关基础知识点及线程生命周期,此期我就一笔带过了,需要重点恶补知识点的同学,可以看下我前两期总结的,都是实打实的干货,篇篇文字并茂,万字长文,一定能够帮助到你。

  • 零基础学Java多线程控制:让你轻松掌握线程操作,有两下子!
  • 零基础学Java多线程:深入理解线程生命周期,有两下子!

摘要

  在Java多线程编程中,掌握线程的创建和管理是至关重要的。,本文将介绍Java中多线程的创建方法,包括继承Thread类和实现Runnable接口两种方式,并通过源代码解析、应用场景案例、优缺点分析等来详细讲解每一种方法的使用和特点,最后通过一个测试案例来完整的复盘一遍,理论+实践 = 百分百掌握。

概述

  在多线程编程中,线程是程序中执行的独立单元。Java中线程的创建有两种常用的方式:继承Thread类和实现Runnable接口,这两种是最基础的创建方式之一,比如还有通过线程池的方式、创建定时等。其中,对于继承Thread类,我们需要重写run()方法,而实现Runnable接口,我们需要实现run()方法。针对如上两者,皆可创建线程对象并调用start()方法来启动线程,如下我就通过对此两种方式来零基础教学,并且也会对这两种方式进行优缺点分析,以便于同学们能够优先自我掌握。

为什么需要多线程?

  可能很多刚入门的小伙伴就会产生疑问,为啥需要多线程?这个问题想必在座的各位曾经都有思考过,所以现在非常能够理解产生这些疑惑的同学们。这里我先就给大家进行分享下个人的理解,无妨大家可以这样想象一下,你在厨房里准备晚餐,如果只有你一个人,你可能需要先切菜,然后煮饭,接着炒菜;但如果你有帮手,你们可以同时进行这些任务,这样晚餐就能更快准备好。同样,在计算机程序中,如果我们能让不同的任务同时进行,程序就能更快地完成工作,也就是所谓的并行处理,同一时间多人进行,从而加快程序的执行速度。

多线程重要吗?

  这点绝对是毋庸置疑的,它非常重要,为啥这么重要??这里我接着给同学们分享。多线程就像是在厨房里多请了几个帮手,每个人都能同时做不同的活儿,这样饭菜就能更快上桌。在电脑程序里,多线程能让程序同时做很多事,就像多个人一起工作一样,效率自然就高了。

  1. 提高效率:想象一下,如果电脑里只有一个程序在运行,它就只能做一件事。但有了多线程,电脑就能像多核大脑一样,同时处理好几个任务,速度自然就快了。

  2. 改善响应性:就像你在玩游戏时,如果电脑还在下载东西,游戏可能会卡顿。但如果用多线程,下载和游戏可以同时进行,互不影响,游戏就能流畅多了。

  3. 资源利用率:多线程就像是把电脑的CPU和内存都用起来,不让它们闲着。这样,电脑的每个部分都能发挥最大作用。

  4. 更好的用户体验:用户就像是顾客,他们希望点菜后能快速上菜。多线程能让程序快速响应用户的操作,就像快速上菜一样,让顾客满意。

  5. 并行处理:有些任务可以分成很多小块,每块都可以同时处理。多线程就像是有很多工人同时工作,这样完成任务的速度就快多了。

  6. 简化设计:有时候,程序设计得太复杂,就像厨房里有很多复杂的机器。多线程可以让程序设计更简单,就像用简单的工具就能做出好菜。

  7. 避免阻塞:如果一个任务卡住了,整个程序可能就会停下来。多线程可以避免这种情况,就像一个厨师忙不过来,其他厨师可以接手继续做。

  8. 利用现代硬件:现在的电脑越来越强大,多线程就像是让这些强大的电脑发挥出它们的最大能力。

  9. 适应性:在一些需要快速反应的场合,比如在线游戏或者股票交易,多线程能让程序更加灵活,快速适应变化。

  10. 错误隔离:如果程序中的一个部分出了问题,多线程可以保证其他部分不受影响,就像一个厨师出错了,其他厨师还可以继续工作。

  总之,多线程就像是请了一群能干的帮手,让程序能更快、更顺畅、更稳定地运行。掌握了多线程,你的程序就能像高效的厨房一样,快速满足用户的需求。

Java中的多线程是如何工作的?

  那么,它究竟是如何工作的呢?这点我们继续往下看。我们都知道Java提供了两种主要的方式来创建线程,这两种方式各有特点,适用于不同的应用场景:

  • 继承Thread类:就像你创建一个新食谱,基于一个已有的食谱进行修改。在Java中,你可以通过创建一个新的类,继承自Thread类,并重写它的run方法来定义你的任务。

  • 实现Runnable接口:这就像是按照食谱做菜,你不需要自己从头开始创造食谱,只需要按照已有的步骤来。在Java中,你可以创建一个实现了Runnable接口的类,并实现它的run方法,然后将其传递给Thread对象。

如何创建和启动线程?

  那么,我们既然了解了线程是如何工作的,那么你们知道它是如何被创建及启动的呢?其实也很简单,创建和启动线程是多线程编程中的基础操作,它们确保了程序能够并行执行多个任务。以下是创建和启动线程的详细步骤,以及它们之间的逻辑联系:

  1. 定义任务

    • 在多线程编程中,每个线程都需要执行一个特定的任务。任务的定义通常通过编写一个run方法来实现。这个方法是线程执行的入口点,包含了线程要执行的所有操作。
  2. 选择线程创建方式

    • 根据你的程序需求,你可以选择继承Thread类或实现Runnable接口来定义你的任务。继承Thread类意味着你的类直接扩展了线程的功能,而实现Runnable接口则需要将你的任务类传递给一个Thread对象。
  3. 创建线程对象

    • 一旦你定义了任务,接下来就是创建线程对象。如果你选择继承Thread类,你将创建该类的实例;如果实现Runnable接口,你需要创建一个Runnable对象,并将该对象作为参数传递给Thread类的构造函数,然后创建Thread对象的实例。
  4. 启动线程

    • 创建线程对象后,你需要调用start()方法来启动线程。这个方法会触发线程的执行,使其进入就绪状态,并最终运行。重要的是要注意,start()方法会隐式地调用你的run方法,因此无需手动调用run
  5. 线程的执行

    • 一旦线程启动,它将按照定义的run方法中的指令执行任务。线程的执行是由Java运行时环境的线程调度器控制的,它会根据系统的线程调度策略来决定何时执行哪个线程。
  6. 线程的生命周期管理

    • 在线程执行过程中,你需要了解线程的生命周期,包括新建、就绪、运行、阻塞和死亡状态。这有助于你更好地控制线程的执行流程,例如,通过适当的同步机制来处理线程间的协作或竞争。
  7. 异常处理

    • 在多线程环境中,异常处理尤为重要。确保你的run方法能够妥善处理可能发生的异常,避免线程因未捕获的异常而意外终止。
  8. 线程的结束

    • 线程完成任务后,应当正确结束。在run方法的末尾,线程会自然结束。如果需要提前结束线程,可以通过中断机制来实现。

  通过上述步骤,你就可以轻松创建和启动线程,使它们能够并行执行任务,从而提高程序的效率和响应性。有一点需要注意,多线程编程需要仔细设计和测试,以确保线程间的同步和资源管理得当,避免出现竞态条件和死锁等问题,这点在日常使用多线程是非常有必要的。

线程的生命周期

  线程也有对应的生命周期,就像人一样,有出生、成长、衰老和死亡的过程,只不过它的不是一模一样。

  • 新建状态:线程被创建,但还没有开始工作。
  • 就绪状态:线程准备好了,等待CPU的调度来执行。
  • 运行状态:线程正在执行它的任务。
  • 阻塞状态:线程因为某些原因(比如等待输入输出操作完成)暂时不能继续执行。
  • 死亡状态:线程的任务执行完毕或者被强制停止。

  需要恶补基础知识点的同学可以看我这篇: 零基础学Java多线程:深入理解线程生命周期,有两下子!

线程同步的重要性

  当多个线程需要访问共享资源时,如果没有适当的同步机制,就可能出现问题,比如数据不一致。Java提供了多种同步机制,比如synchronized关键字,来确保多个线程不会同时修改同一个资源。

线程池有啥好处?

  想象一下,如果你每次做饭都要买一套新的厨具,这将是多么浪费。线程池就像是共享厨具,你可以重复使用它们,这样可以节省资源,提高效率。

何为线程安全?

  编写线程安全的代码意味着你的程序在多线程环境下也能正常工作,不会出现数据错乱或者程序崩溃的问题。

线程的高级特性

  除了基本的线程操作,Java还提供了一些高级特性,如线程局部变量、中断处理和线程池等,这些特性可以进一步提高多线程程序的性能和可维护性。这些我们就日后再谈。

创建线程方式

  那么,有了如上知识点的铺垫,那接下里,我就带着大家从零开始手撸代码,步步为营。

  总所周知,在程序的世界里,线程是执行的独立单元,那么我们就来耍耍,它究竟要如何创建?其实我们压根不需要重复造轮子,我们只需要使用原生的就能满足。对于Java本身而言,它就提供了多种方式来创建线程,其中最基本的两种当属继承Thread类和实现Runnable接口。接下来,我们将通过零基础实战教学,逐步深入这两种方法的实现和运用。

方式1:继承Thread类

  我们先来介绍第一种,通过定义一个类直接继承Thread类,然后重写run()即可方法即可,上手即会。示例代码如下:

/**
 * @Author bug菌
 * @Source 公众号:猿圈奇妙屋
 * @Date 2024-04-15 22:23
 */
public class MyThread extends Thread {
    
    @Override
    public void run() {
        // 线程执行的代码逻辑
        System.out.println("线程执行中...");
    }
}

代码解析:

  如上代码我先定义了一个名为MyThread的线程类,继承Thread。这个类中我重写了Thread类中的run()方法,run()方法中包含了线程执行的代码逻辑,实际业务实际修改,我只是做演示。在这个例子中,run()方法只是简单地打印出一条消息"线程执行中…",而实际项目开发中,则是写对应的业务逻辑即可。

  总言而之,通过创建MyThread的对象并调用start()方法,可启动一个新的线程,并执行其中的代码逻辑。

  而如下我再讲一下我提到的另一种创建方式

方式2:实现Runnable接口

  我们先来介绍第一种,通过定义一个类直接继承Thread类,然后重写run方法,即可。示例代码如下:

/**
 * @Author bug菌
 * @Source 公众号:猿圈奇妙屋
 * @Date 2024-04-15 22:24
 */
public class MyRunnable implements Runnable {
    
    @Override
    public void run() {
        // 线程执行的代码逻辑
        System.out.println("线程执行中...");
    }
}

代码解析:

  此段代码与上个原理是不太相同,但实现目的是一致的,即创建线程。我先定义了一个名为MyRunnable的类,并且实现了Runnable接口。Runnable接口中只有一个run()方法需要实现。

  在MyRunnable类中,重写了run()方法。在run()方法中,我们可以定义线程执行的代码逻辑。在这个例子中,我们简单地输出了一条信息"线程执行中…",同理,对于实际项目开发中,则是写对应的业务逻辑即可。

  这样,当我们将MyRunnable实例传给一个Thread对象,并调用start()方法启动线程时,线程就会执行run()方法中的代码逻辑。

案例演示

  接下来,我们就运用上述理论知识,来实际战斗一波。

方式一:继承Thread类-创建线程

测试代码

示例代码如下:

/**
 * @Author bug菌
 * @Source 公众号:猿圈奇妙屋
 * @Date 2024-04-15 22:23
 */
public class MyThreadTest {

    public static void main(String[] args) {
        MyThread thread = new MyThread();
        thread.start();
    }
}
案例测试结果

  根据如上的测试用例,作者在本地进行测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加其他的测试数据或测试方法,以便于进行熟练学习以此加深知识点的理解。

案例测试代码分析

  根据如上测试用例,在此我给大家进行深入详细的解读一下测试代码,以便于更多的同学能够理解并加深印象。

  如上代码它是一个简单的多线程程序的示例。下面是对这段代码的分析,希望能帮助到你:

  1. 类定义:先定义一个名为 MyThreadTest 的公共类。在Java中,公共类意味着它可以被任何其他类访问。

  2. 主方法main 方法是Java程序的入口点。它是一个静态方法,这意味着它属于类本身而不是类的实例。这个方法接受一个字符串数组 args 作为参数,这通常用于命令行参数。

  3. 线程创建:在 main 方法中,创建了一个 MyThread 类的实例,并且调用了它的 start() 方法。MyThread 类没有在这段代码中给出,但我们可以推断它是一个继承了 Thread 类或者实现了 Runnable 接口的类,因为它有一个 start() 方法。

  4. 线程启动:调用 start() 方法实际上会创建一个新的线程,并在这个新线程中执行 MyThread 类的 run() 方法。run() 方法是 Thread 类的一个抽象方法,必须在子类中实现。MyThread 类的 run() 方法中应该包含了线程执行的代码。

  5. 多线程执行:一旦 start() 被调用,MyThread 实例将在它自己的线程中并行执行,与主线程(即包含 main 方法的线程)同时运行。

  6. 代码不完整:这段代码只是一个框架,缺少 MyThread 类的具体实现。为了使程序完整,我们需要 MyThread 类的实现,其中至少包含一个重写的 run() 方法。

  7. 线程的生命周期:当 main 方法执行完毕,程序将结束。如果 MyThread 线程还没有执行完,它将继续运行,直到它的 run() 方法执行完毕。

  8. 线程安全:这段代码没有显示任何关于线程同步或线程安全的措施。如果 MyThread 类的 run() 方法中访问共享资源,那么可能需要考虑线程安全问题。

  9. 错误处理:代码中没有显示任何错误处理机制。在实际应用中,线程可能会抛出异常,因此可能需要捕获并适当处理这些异常。

  10. 资源管理:如果 MyThread 使用了需要关闭的资源(如文件、网络连接等),则需要确保这些资源被适当地关闭,无论是在 run() 方法的末尾还是在 finally 块中。

方式二:实现Runnable接口-创建线程

案例测试代码

示例代码如下:

/**
 * @Author bug菌
 * @Source 公众号:猿圈奇妙屋
 * @Date 2024-04-15 22:24
 */
public class MyRunnableTest {

    public static void main(String[] args) {
        MyRunnable runnable = new MyRunnable();
        Thread thread = new Thread(runnable);
        thread.start();
    }
}
案例测试结果

  根据如上的测试用例,作者在本地进行测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加其他的测试数据或测试方法,以便于进行熟练学习以此加深知识点的理解。

本地实际运行结果展示如下:

  非常直观可以看到,从执行函数中执行了start方法,皆控制台成功输出打印了线程体中执行run方法的逻辑业务;输出了如下内容:

线程执行中...
案例测试代码分析

  根据如上测试用例,在此我给大家进行深入详细的捋一捋测试代码的全过程,以便于更多的同学能够加深印象并且把它吃透。

  这段代码展示了如何使用 Runnable 接口来创建一个线程。以下是对这段代码案例的详细分析:

  1. 类定义:定义了一个名为 MyRunnableTest 的公共类。这个类包含了 main 方法,它是程序的入口点。

  2. 创建 Runnable 实例:在 main 方法中,首先创建了一个 MyRunnable 类的实例。MyRunnable 应该是一个实现了 Runnable 接口的类,这意味着它必须实现 Runnable 接口中的 run 方法。

  3. 创建线程:接着,使用 MyRunnable 实例作为目标,创建了一个新的 Thread 对象。Thread 构造函数接受一个 Runnable 对象作为参数,这个 Runnable 对象定义了线程要执行的任务。

  4. 启动线程:通过调用 thread.start() 方法,新的线程被启动。这会导致 MyRunnable 实例的 run 方法在新线程中执行。

  5. 线程的并行执行:一旦 start() 方法被调用,MyRunnablerun 方法将在它自己的线程中并行执行,与主线程(即执行 main 方法的线程)同时运行。

  6. 代码的不完整性:这段代码没有提供 MyRunnable 类的实现。为了使程序完整,我们需要 MyRunnable 类的实现,特别是 run 方法的实现。

  7. 线程生命周期main 方法执行完毕后,如果 MyRunnable 线程还没有执行完,它将继续运行,直到 run 方法执行完毕。

  8. 线程安全:如果 MyRunnable 类的 run 方法中访问了共享资源,那么需要考虑线程安全问题,确保对这些资源的访问是同步的。

  9. 错误处理:这段代码没有显示任何错误处理机制。在实际应用中,run 方法可能会抛出异常,因此可能需要在 run 方法中添加异常处理逻辑。

  10. 资源管理:如果 MyRunnable 使用了需要关闭的资源,如文件、网络连接等,需要确保这些资源在使用完毕后被适当地关闭。

  11. 线程的命名:创建 Thread 对象时,可以通过构造函数传递一个字符串参数来为线程命名,这有助于在调试时识别线程。

  12. 线程优先级:可以通过设置线程的优先级来影响线程的调度,但这通常不是线程管理的首选方法。

  这段代码是使用 Runnable 接口进行多线程编程的一个基本示例。通过这种方式,可以将任务的执行逻辑与线程的创建和管理分离,从而提高代码的可读性和可维护性。

小结

  那么针对上述两种创建线程的方式,它们之间有何优劣之分呢?其实是有的,这也需要具体分场景,相对而论。

优缺点分析

继承Thread类方式

优点:

  • 简单直观,代码量较少。

缺点:

  • 由于Java不支持多继承,如果已经继承了其他类,则无法再使用继承Thread类的方式创建线程。

实现Runnable接口方式

优点:

  • 避免了单继承的限制,可以同时实现其他接口。
  • 实现了解耦,线程对象与线程执行的逻辑分离。

缺点:

  • 代码稍微复杂一些。

  希望如上优劣分析,同学们在面对第一次学习的过程中,可以优先选择自己最先能掌握的方式,而不是一概而论,有条件的同学,则可以都掌握的熟练。

类代码方法介绍

如下我梳理了下针对如上两种创建线程的方式之间常用到的方法,仅供参考:

Thread类

  • start(): 启动线程,使其开始执行run()方法中的代码。
  • run(): 线程执行的代码逻辑,需要在子类中重写。

Runnable接口

  • run(): 线程执行的代码逻辑,需要在实现类中实现。

测试用例

  这里我再通过一个案例测试带着大家把上边的知识点串联起来,进行实战演示一波,同学们看好了。

测试代码

/**
 * @Author bug菌
 * @Source 公众号:猿圈奇妙屋
 * @Date 2024-04-15 22:37
 */
public class Test {

    public static void main(String[] args) {
        MyThread thread1 = new MyThread();
        thread1.start();

        MyRunnable runnable = new MyRunnable();
        Thread thread2 = new Thread(runnable);
        thread2.start();
    }
}

测试结果

  针对如上测试代码,这里我本地进行实际测试一波,结果仅供参考,有条件的同学们也可以自己本地实践一下。
  

测试代码解析

  针对如上测试代码,这里我再具体给大家讲解下,希望能够更透彻的帮助大家理解。测试用例定义了一个名为Test的公共类,其中包含main方法,这是Java程序的入口点。在main方法中,创建并启动了两个线程:thread1thread2

  1. 注释部分

    • 代码顶部的注释包含了我本地编辑器的信息、来源和日期。这通常用于说明代码的出处和编写时间,也建议大家都设置一下。
  2. main方法

    • main方法是程序执行的起点。它接收一个字符串数组args作为参数,这个数组通常用于传递命令行参数给程序(这是学习Java最基础的了,这里我也重提一下)。
  3. 创建并启动线程thread1

    • MyThread是一个继承自Thread的类,这意味着它可能是一个自定义的线程类。在Test类的main方法中,创建了MyThread的一个实例thread1,然后调用了它的start方法来启动线程。start方法会创建一个新的执行线程,并在这个线程中执行MyThread类的run方法。
  4. 创建并启动线程thread2

    • MyRunnable是一个实现Runnable接口的类。Runnable接口是Java中定义线程执行任务的一种方式。在Test类的main方法中,创建了MyRunnable的一个实例runnable,然后创建了一个新的Thread对象thread2,将runnable作为目标(target)传递给Thread构造函数。最后,调用thread2start方法来启动线程。这将导致Thread对象在新的执行线程中执行run方法,run方法将调用runnablerun方法。

  总而言之,这个案例我向大家演示了两种在Java中创建和启动线程的方式:一种是通过继承Thread类,另一种是通过实现Runnable接口。两种方式都可以定义线程的执行任务,但是实现Runnable接口的方式更加灵活,因为它允许你将任务的执行逻辑与线程的创建和控制逻辑分离开来。

  但是,这里我也要多提一嘴,需要注意的是,我这个案例中并没有提供MyThreadMyRunnable类的实现细节,所以我们无法知道这些类的run方法具体做了什么。为了完全理解这段代码的行为,我们需要这些类的完整定义,也就是所谓的业务逻辑,希望实战的同学能够把它运用上。

小结

  讲解到这里,我对本段进行个收尾工作啦,帮助大家一起梳理下。本文主要通过介绍Java中多线程的创建方法,详细讲解了继承Thread类和实现Runnable接口两种创建线程方式的使用和特点。同时讲解了每种方式的优缺点,及对比了两者的优缺点,最后通过相应的类代码方法介绍和实战演示该创建线程的代码案例来充分演示这几种创建方式实践,最后对案例代码进行解读及分析,帮助到薄弱的同学更快速的入手掌握。

总结

  在此,想必大家应该就能体会到了,多线程是Java开发中常用的技术,能够提高程序的执行效率。通过本文的学习,我们了解了Java中多线程的创建方法,包括继承Thread类和实现Runnable接口两种方式。在实际开发中,我们可以根据需求选择合适的方式来创建线程,从而提高程序的性能和效率。

结尾

  最后,我希望本文能够帮助大家理解并掌握Java中多线程的创建方法,并在实际开发中能够灵活运用它,而不仅仅是为了学而学,一定要把它运用到实际场景中去,发挥线程的功能。多线程它是有一个广阔而有趣的领域,希望大家也能够进一步深入学习和探索,提高自己在多线程编程方面的能力,这对项目开发能力有着极大的提升。

  … …

  好啦,这期的内容就基本接近尾声啦,若你想学习更多,你可以看看专栏的导读篇《「滚雪球学Java」教程导航帖》,本专栏致力打造最硬核 Java 零基础系列学习内容,🚀打造全网精品硬核专栏,带你直线超车;欢迎大家订阅持续学习。功不唐捐,久久为功!

「赠人玫瑰,手留余香」,咱们下期拜拜~~

附录源码

  如上涉及所有源码均已上传同步在「Gitee」,提供给同学们一对一参考学习,辅助你更迅速的掌握。

☀️建议/推荐你

  无论你是计算机专业的学生,还是对编程感兴趣的跨专业小白,都建议直接入手「滚雪球学Java」专栏;该专栏不仅免费,bug菌还郑重承诺,只要你学习此专栏,均能入门并理解Java SE,以全网最快速掌握Java语言,每章节源码均同步「Gitee」,你真值得拥有;学习就像滚雪球一样,越滚越大,带你指数级提升。

  码字不易,如果这篇文章对你有所帮助,帮忙给bugj菌来个一键三连(关注、点赞、收藏) ,您的支持就是我坚持写作分享知识点传播技术的最大动力。

  同时也推荐大家关注我的硬核公众号:「猿圈奇妙屋」 ;以第一手学习bug菌的首发干货,不仅能学习更多技术硬货,还可白嫖最新BAT大厂面试真题、4000G Pdf技术书籍、万份简历/PPT模板、技术文章Markdown文档等海量资料,你想要的我都有!

📣关于我

我是bug菌,CSDN | 掘金 | InfoQ | 51CTO | 华为云 | 阿里云 | 腾讯云 等社区博客专家,C站博客之星Top30,华为云2023年度十佳博主,掘金多年度人气作者Top40,51CTO年度博主Top12,掘金/InfoQ/51CTO等社区优质创作者;全网粉丝合计 20w+;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试真题、4000G PDF电子书籍、简历模板等海量资料,你想要的我都有,关键是你不来拿。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/897335.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

代码审计-Python Flask

1.Jinjia2模版注入 Flask是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2。jinja2是Flask作者开发的一个模板系统,起初是仿django模板的一个模板引擎,为Flask提供模板支持,由于…

KASan部署、使用与原理分析

文章目录 前言1、概述2、使用方法3、测试用例3.1、检测加载的内核模块3.2、检测调用的内核模块3.3、通过系统调用检测3.4、检测编译到Linux内核中的内核模块 4、工作原理4.1、影子内存(Shadow Memory)4.2、内存状态(Memory States&#xff09…

海南聚广众达电子商务咨询有限公司靠谱吗怎么样?

在当今这个数字化浪潮席卷全球的时代,抖音电商以其独特的魅力成为了众多商家争相入驻的新蓝海。而在这片浩瀚的电商海洋中,如何找到一家既专业又可靠的合作伙伴,成为了众多商家心中的一大难题。今天,我们就来深入剖析一下海南聚广…

爬虫日常实战

爬取美团新闻信息,此处采用两种方法实现: 注意点:因为此处的数据都是动态数据,所以一定要考虑好向下滑动数据包会更新的情况,不然就只能读取当前页即第一页数据,方法一通过更新ajax数据包网址页数&#xf…

转变软件交付方式:通过统一 API 和测试策略提高质量和速度

API 在当今的数字化转型中至关重要,但无缝交付也同样重要。然而,许多组织仍然分散其 API 开发和 UI 测试流程,导致问题检测延迟、发布时间延长,甚至遗漏错误。在快节奏的环境中,这种方法是不可持续的,因为上…

Java调用上传文件接口

以 QAnthing 上传文件(POST)接口为例,展示Java如何调用上传文件接口。 接口文档如下: QAnthign接口文档地址 上代码: RestTemplate 版 /** * * param url 接口地址 * param filePath 文件本地路径 */ public vo…

【C++】踏上C++学习之旅(三):“我“ 与 “引用“ 的浪漫邂逅

文章目录 前言1. "引用"的概念1.1 "引用"的语法 2. "引用"的特性3. "引用"的使用场景3.1 "引用"做参数3. 2 "引用"做返回值3.2.1 "引用"做返回值时需要注意的点 4. 常引用5. "引用"在底层的实…

【设计模式系列】命令模式

目录 一、什么是命令模式 二、命令模式的角色 三、命令模式的典型应用场景 四、命令模式在Runnable中的应用 一、什么是命令模式 命令模式(Command Pattern)是一种行为设计模式,它将一个请求或简单操作封装为一个对象。这个模式提供了一种…

在使用new Date()生成时间戳时,发现数据库中 的时间总是多出一秒钟。

项目汇报的时候,进一步研究问题 insert into t_tax_file(task_id, task_no, business_type, file_name, file_url, creator_id, created_time, modifier_id,modified_time)value (10, taskNo测试, 1, 文件名称, 文件地址, 1, 2024-10-21 10:25:21.889, 1, 2024-10-…

CCF-BDCI大数据与计算智能大赛TOP4-京东生鲜

2023 CCF 大数据与计算智能大赛《线上线下全场景生鲜超市库存履约一体化决策》top4南山论剑 摘要1 数据预处理1.1 数据整合1.2 数据划分 2 特征工程2.1 静态特征2.2 动态特征 3 方案设计3.1 数据构造3.2 模型训练3.3 模型融合3.4库存分配3.5 方案对比 链接: CCFBDCI-线上线下全…

对BSV区块链下一代节点Teranode的答疑解惑(上篇)

​​发表时间:2024年8月7日 2024年初BSV区块链研发团队揭晓了即将到来的Teranode更新的突破性特性,这些特性将显著提升网络的效率和处理速度,使BSV区块链能够达到百万级TPS。 Teranode的项目主管Siggi Oskarsson强调:“当你阅读这…

uniapp项目结构基本了解

基本结构的解释 App.vue:应用的根组件,定义全局布局和逻辑。pages/:存放各个页面的 .vue 文件,定义应用的具体页面和功能模块。main.js:应用入口文件,初始化应用,挂载 App.vue。manifest.json&…

[Linux进程概念]命令行参数|环境变量

目录 一、命令行参数 1.什么是命令行参数 2.为什么要有命令行参数 (1)书写的代码段 (2)实际的代码段 3.Linux中的命令行参数 二、环境变量 1.什么是环境变量? 2.获取环境变量 (1)指令…

基于Multisim电子配料秤电路设计(含仿真和报告)

【全套资料.zip】电子配料秤电路设计Multisim仿真设计数字电子技术 文章目录 功能一、Multisim仿真源文件二、原理文档报告资料下载【Multisim仿真报告讲解视频.zip】 功能 电子配料秤仿真功能: 准确测量物体重量,精确度0.1Kg使用两位数码管显示重量信息 使用拨码…

深度学习 基本函数01

np.dot 是 NumPy 库中的一个函数,用于计算两个数组的点积(也称为内积或数量积)。点积是两个向量的对应元素乘积之和。 np.random.normal 是 NumPy 库中的一个函数,用于生成符合正态分布(也称为高斯分布)的…

jmeter用csv data set config做参数化1

在jmeter中,csv data set config的作用非常强大,用它来做批量测试和参数化非常好用。 csv data set config的常用配置项如下: Variable Names处,写上源文件中的参数名,用于后续接口发送请求时引用 Ignore first line…

Mybatis多对一查询的配置及两种方法的使用示例对比以及Mybatis一对多查询两种方法使用示例及对比

一、Mybatis多对一查询的配置及两种方法的使用示例对比 为了试验Mybatis多对一的查询,我们先在数据库中建两个表,一个城市表,一个市区表,一个城市有多个区是一个一对多的关系;多个区对应一个城市是一个多对一的关系。建…

spring源码拓展点3之addBeanPostProcesser

概述 在refresh方法中的prepareBeanFactory方法中,有一个拓展点:addBeanPostProcessor。即通过注入Aware对象从而将容器中的某些值设置到某个bean中。 beanFactory.addBeanPostProcessor(new ApplicationContextAwareProcessor(this));aware接口调用 …

ThinkPad T480拆机屏幕改装:便携式显示器DIY指南

ThinkPad T480拆机屏幕改装:便携式显示器DIY指南 本文记录了将旧笔记本电脑 T480 拆机屏幕改装为便携式显示器的全过程。作者在决定升级设备后,选择通过 DIY 方式利用原有的屏幕资源。文章详细介绍了屏幕驱动板的安装、螺丝孔的剪裁、排线连接及固定的步…

[DB] NSM

Database Workloads(数据库工作负载) 数据库工作负载指的是数据库在执行不同类型任务时所需的资源和计算方式,主要包括以下几种类型: 1. On-Line Transaction Processing (OLTP) 中文:联机事务处理解释:…