当前位置: 首页 > news >正文

多线程JUC(一)

目录

  • 前言
  • 一、多线程的三种实现方式
    • 1.继承Thread类
    • 2.实现Runnable接口
    • 3.利用Callable接口和Future接口
    • 4.三种方式对比
  • 二、常见的成员方法
    • 1.getName、setName、currentThread、sleep
    • 2.线程的优先级
    • 3.守护线程
    • 4.插入线程
  • 三、线程安全
    • 1.线程的生命周期
    • 2.同步代码块
    • 3.同步方法
    • 4.lock锁


前言

线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程的实际运作单位。简单理解:应用软件中互相独立,可以同时运行的功能。

进程是程序执行的基本执行实体。如下图,每一个运行的程序都对应着一个进程。

在这里插入图片描述

为什么要有多线程?

如下图所示,当JVM在内存中为变量开辟空间时是需要时间的,尽管时间很短,但是在这段时间内CPU会处于空闲状态,因此就没有充分利用CPU。多线程就可以让CPU在JVM在内存开辟空间的这段时间去执行其他程序,从而提高CPU的利用率。
在这里插入图片描述

一、多线程的三种实现方式

1.继承Thread类

步骤如下:

  1. 自己定义一个类继承Thread
  2. 重写run方法
  3. 创建自己写的类的对象,并启动线程(start方法用来启动线程)
public class MyThread extends Thread{@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println(getName() + "HelloWorld!");}}
}
public class ThreadDemo1 {public static void main(String[] args) {/*多线程的第一种启动方式1.自己定义一个类继承Thread2.重写run方法3,创建子类的对象,并启动线程(start方法用来启动线程)*///这里设置两个线程,来看线程是不是交替执行的MyThread mt1 = new MyThread();MyThread mt2 = new MyThread();//设置线程的名字//setName方法是直接继承于Thread类的mt1.setName("线程1");mt2.setName("线程2");mt1.start();mt2.start();}
}

在这里插入图片描述
通过结果我们可以发现,在多线程模式下,两个线程是会交替执行的,充分利用CPU。

2.实现Runnable接口

步骤如下:

  1. 定义一个类实现Runnable接口
  2. 重写里面的run方法
  3. 创建自己类的对象
  4. 创建一个Thread对象,然后将自己类的对象传入,并开启线程。
public class MyRun implements Runnable{@Overridepublic void run() {for (int i = 0; i < 100; i++) {//获取当前线程的对象Thread t = Thread.currentThread();//因为不能直接使用Thread里面的方法,所以必须先获取当前进程,才可以获取名字System.out.println(t.getName() + "HelloWorld");}}
}
public class ThreadDemo {public static void main(String[] args) {/*多线程的第二种启动方式1.自己定义一个类实现Runnable接口2.重写里面的run方法3.创建自己的类的对象4.创建一个Thread类的对象,并开启线程*///创建MyRun对象//表示多线程要执行的任务MyRun mr = new MyRun();//创建线程对象//两个线程执行同一个任务Thread t1 = new Thread(mr);Thread t2 = new Thread(mr);//设置名字t1.setName("线程1");t2.setName("线程2");t1.start();t2.start();}
}

在这里插入图片描述

3.利用Callable接口和Future接口

前两种方式中的run方法没有返回值,所以前两种方式就无法获取多线程运行的结果,只能在控制台打印信息。 而第三种方式就可以获取到多线程运行的结果

步骤如下:

  1. 创建一个类实现Callable接口
  2. 重写call方法(有返回值,表示多线程运行的结果)
  3. 创建自己类的对象(表示多线程要执行的任务)
  4. 创建FutureTask的对象( 作用是管理多线程运行的结果)
  5. 创建Thread类的对象,并启动线程

//Callable接口存在泛型,表示多线程返回值的类型
public class MyCallable implements Callable<Integer> {@Overridepublic Integer call() throws Exception {int sum = 0;for (int i = 1; i <= 100; i++) {sum += i;}return sum;}
}
public class ThreadDemo {public static void main(String[] args) throws ExecutionException, InterruptedException {/*多线程的第三种实现方式:特点:可以获取到多线程运行的结果1.创建一个类MyCallable实现Callable接口2.重写call方法(有返回值,表示多线程运行的结果)3.创建MyCallable的对象(表示多线程要执行的任务)4.创建FutureTask的对象(作用是管理多线程运行的结果)5.创建Thread类的对象,并启动线程*/MyCallable mc = new MyCallable();FutureTask<Integer> ft = new FutureTask<>(mc);//启动线程Thread t = new Thread(ft);t.start();//打印结果//要先启动线程,否则打印不出来结果,虚拟机会一直运行System.out.println(ft.get());}
}

在这里插入图片描述

4.三种方式对比

在这里插入图片描述

二、常见的成员方法

1.getName、setName、currentThread、sleep

getName方法是用来获取线程的名字,但是如果不给线程设置名字,那么默认的名字是什么呢?

如果我们没有给线程设置名字,线程也是有默认名字的。格式:Thread-X(X是序号,从0开始)。

public class MyThread extends Thread{@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println(getName() + "@" + i);}}
}
public class ThreadDemo1 {public static void main(String[] args) {MyThread t1 = new MyThread();MyThread t2 = new MyThread();System.out.println(t1.getName());System.out.println(t2.getName());}
}

在这里插入图片描述

我们可以直接通过setName方法对线程设置名字,我们也可以直接通过构造方法来设置名字。但是我们自己写的类没有办法继承父类的构造方法,所以只能自己写一个带参数的构造方法,通过super关键字来调用父类的构造方法。

public class MyThread extends Thread{public MyThread(String name) {super(name);}public MyThread() {}@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println(getName() + "@" + i);}}
}
public class ThreadDemo1 {public static void main(String[] args) {MyThread t1 = new MyThread("坦克");MyThread t2 = new MyThread("飞机");t1.start();t2.start();}
}

在这里插入图片描述

currentThread()方法是静态方法,我们在main方法中直接调用可以获取到执行main方法的那条线程。可以发现执行main方法的线程名字就是“main”。main线程的作用就是去调用main方法,并执行里面的代码。 哪个线程执行到currentThread()方法,就会获取到哪个线程

public class ThreadDemo1 {public static void main(String[] args) {/*static Thread currentThread()           获取当前线程的对象*/Thread t = Thread.currentThread();System.out.println(t.getName());}
}

在这里插入图片描述

sleep方法也是静态方法,哪条线程执行到这个方法,那么哪条线程就会在这里停留对应的时间。方法的参数,就表示睡眠的时间,单位是ms。时间到了之后,线程就是自动醒来,继续执行下面的代码。

public class ThreadDemo1 {public static void main(String[] args) throws InterruptedException {/*static void sleep(long time)            让线程休眠指定的时间,单位为毫秒*/System.out.println("11");Thread.sleep(1000);System.out.println("22");}
}

先打印11后,线程会停留1s才会打印22。

在这里插入图片描述

2.线程的优先级

在这里插入图片描述

Java中对线程的调度是抢占式调度,强调一个随机性。CPU在什么时候执行哪条线程是不确定的,优
先级越高,随机到的概率也就越大。Java中优先级最小为1,最大为10,如果没有设置,那么默认
优先级为5

public class MyRunnable implements Runnable{@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName() + "@" + i);}}
}
public class ThreadDemo2 {public static void main(String[] args) {/*final int getPriority()             获取线程的优先级*/MyRunnable mr = new MyRunnable();Thread t1 = new Thread(mr, "坦克");Thread t2 = new Thread(mr, "飞机");System.out.println(t1.getPriority());System.out.println(t2.getPriority());}
}

可以看到,默认的线程优先级为5。
在这里插入图片描述

对于setPriority方法,t1我设置优先级为1,t2设置优先级为10,只能说t2抢占CPU的概率较大。

public class ThreadDemo2 {public static void main(String[] args) {/*setPriority(int newPriority)        设置线程的优先级*/MyRunnable mr = new MyRunnable();Thread t1 = new Thread(mr, "坦克");Thread t2 = new Thread(mr, "飞机");t1.setPriority(1);t2.setPriority(10);t1.start();t2.start();}
}

两次的运行结果可以看出来,优先级低的线程也是有可能先执行完的,只不过概率低罢了。

在这里插入图片描述

在这里插入图片描述

3.守护线程

我们可以将一个线程设置为守护线程,当其他的非守护线程执行完毕之后,守护线程会陆续结束。(守护线程不会立马就停止,可能会再继续运行一段时间才结束)。

应用场景:

例如当两个人利用qq正在聊天,A要给B发一个文件,那么这个时候我们可以吧聊天窗口看作是一个线程,发送的文件也可以看作是一个线程。如果说把聊天窗口(线程1)给关掉了,线程2也就没有存在的必要了,此时就可以把传输文件设置为守护线程。
在这里插入图片描述

有下面的两个线程,将第二个线程设置为守护线程,可以发现在非守护线程执行完后,守护线程没有执行完毕,而是执行了一点就停止了。

public class MyThread1 extends Thread{@Overridepublic void run() {for (int i = 1; i <= 5; i++) {System.out.println(getName() + "----" + i);}}
}
public class MyThread2 extends Thread{@Overridepublic void run() {for (int i = 1; i <= 20; i++) {System.out.println(getName() + "----" + i);}}
}
public class ThreadDemo3 {public static void main(String[] args) {/*final void setDaemon(boolean on)            设置为守护线程*/MyThread1 t1 = new MyThread1();MyThread2 t2 = new MyThread2();t1.setName("女神");t2.setName("备胎");//设置为守护线程t2.setDaemon(true);t1.start();t2.start();}
}

在这里插入图片描述

4.插入线程

插入线程是为了让某个线程先于另一个线程执行完。

public class MyThread extends Thread{public MyThread(String name) {super(name);}public MyThread() {}@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println(getName() + "@" + i);}}
}
public class ThreadDemo4 {public static void main(String[] args) throws InterruptedException {/*public final void join()            插入线程*/MyThread t = new MyThread();t.setName("土豆");t.start();//表示把t这个线程,插入到当前线程之前//当前线程是main线程t.join();for (int i = 0; i < 10; i++) {System.out.println("main线程" + i);}}
}

确实是土豆线程先于main线程执行。

在这里插入图片描述

三、线程安全

1.线程的生命周期

线程的一个周期内有五种状态

在这里插入图片描述

2.同步代码块

现在有如下的需求:

某电影院正在售卖电影票,一共有100张票,共有三个窗口售卖,设计一个程序模拟电影院卖票。

public class MyThread extends Thread{//该类的所有对象都共享同一个变量static int ticket = 0;@Overridepublic void run() {while (true) {if (ticket < 100) {try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}ticket++;System.out.println(getName() + "正在卖第" + ticket + "张票");}else {break;}}}
}
public class ThreadSafeDemo1 {public static void main(String[] args) {MyThread t1 = new MyThread();MyThread t2 = new MyThread();MyThread t3 = new MyThread();t1.setName("窗口1");t2.setName("窗口2");t3.setName("窗口3");t1.start();t2.start();t3.start();}
}

通过上述代码运行之后,会发现有一些问题,不同的窗口会出现卖的票相同的情况。这是由于线程抢夺CPU的随机性导致的。窗口1卖出之后还没来得及打印CPU就被窗口3线程抢走,最后导致数据的错误。

在这里插入图片描述
在这里插入图片描述

为了避免上述的问题,此时就需要用到同步代码块。它可以把能被操作的共享数据锁起来,只有等一个线程解锁之后,另一个线程才可以对共享数据进行操作。不过当线程出来之后,它也可以继续抢夺CPU的使用权。所以一个线程也可以多次执行。类比于上厕所。

特点:

  1. 锁默认打开,有一个线程进去了,锁自动关闭
  2. 里面的代码全部执行完毕,线程出来,锁自动打开
    在这里插入图片描述

对于同步代码块中传入的锁对象,必须要确保是唯一的,所以一般使用当前类的字节码文件来当做参数进行传入。

public class MyThread extends Thread{//该类的所有对象都共享同一个变量static int ticket = 0;@Overridepublic void run() {while (true) {synchronized (MyThread.class) {if (ticket < 100) {try {Thread.sleep(100);} catch (InterruptedException e) {throw new RuntimeException(e);}ticket++;System.out.println(getName() + "正在卖第" + ticket + "张票");}else {break;}}}}
}
public class ThreadSafeDemo1 {public static void main(String[] args) {MyThread t1 = new MyThread();MyThread t2 = new MyThread();MyThread t3 = new MyThread();t1.setName("窗口1");t2.setName("窗口2");t3.setName("窗口3");t1.start();t2.start();t3.start();}
}

可以发现没有个重复票的情况。到最后,线程3一直抢夺到CPU的使用权。

在这里插入图片描述

3.同步方法

同步方法就是把synchronized关键字加到方法上
在这里插入图片描述

特点:

  1. 同步方法是锁住方法里面所有的代码。
  2. 锁对象不能自己指定。如果方法是非静态的,锁对象就是this(当前方法的调用者);如果方式静态的,那么锁对象就是当前类的字节码文件。

method方法是一个同步方法。

public class MyRunnable implements Runnable{int ticket = 0;@Overridepublic void run() {while (true) {if (method()) break;}}private synchronized boolean method() {if (ticket == 100) {return true;}else {try {Thread.sleep(100);} catch (InterruptedException e) {throw new RuntimeException(e);}ticket++;System.out.println(Thread.currentThread().getName() + "卖出第" + ticket + "张票");}return false;}
}
public class ThreadSafeDemo2 {public static void main(String[] args) {MyRunnable mr = new MyRunnable();Thread t1 = new Thread(mr, "窗口1");Thread t2 = new Thread(mr, "窗口2");Thread t3 = new Thread(mr, "窗口3");t1.start();t2.start();t3.start();}
}

在这里插入图片描述

4.lock锁

synchronized关键字加的锁是自动打开和释放的,如果想要手动的去加锁和释放锁,就需要一个新的锁对象Lock。

Lock中提供了获得锁和释放锁的方法:
void lock() 获得锁
void unlock() 释放锁

Lock是接口 ,不可以直接实例化,只能用它的实现类ReentrantLock来实例化。

public class MyThread extends Thread{static int ticket = 0;//创建锁对象static Lock lock = new ReentrantLock();@Overridepublic void run() {while (true) {lock.lock();if (ticket == 100) {break;}else {try {Thread.sleep(10);} catch (InterruptedException e) {throw new RuntimeException(e);}ticket++;System.out.println(getName() + "卖出第" + ticket + "张票");}lock.unlock();}}
}
public class ThreadSafeDemo3 {public static void main(String[] args) {MyThread t1 = new MyThread();MyThread t2 = new MyThread();MyThread t3 = new MyThread();t1.setName("窗口1");t2.setName("窗口2");t3.setName("窗口3");t1.start();t2.start();t3.start();}
}

上述代码会出现一些问题,当卖到100张票时程序并没有停止运行。这是因为发生了死锁现象,当窗口2线程执行到ticket==100时,会直接跳出循环,以至于后面的lock.unlock()释放锁代码没有执行,导致窗口1和窗口3线程会一直停留在lock.lock() 这句代码处,导致程序无法停止。

在这里插入图片描述

为了解决上述问题,我们可以利用try…catch…finally结构,将释放锁的代码写到finally部分(finally中的代码是一定会执行的)。

public class MyThread extends Thread{static int ticket = 0;//创建锁对象static Lock lock = new ReentrantLock();@Overridepublic void run() {while (true) {//加锁lock.lock();try {if (ticket == 100) {break;}else {Thread.sleep(10);ticket++;System.out.println(getName() + "卖出第" + ticket + "张票");}} catch (InterruptedException e) {throw new RuntimeException(e);} finally {//释放锁lock.unlock();}}}
}
public class ThreadSafeDemo3 {public static void main(String[] args) {MyThread t1 = new MyThread();MyThread t2 = new MyThread();MyThread t3 = new MyThread();t1.setName("窗口1");t2.setName("窗口2");t3.setName("窗口3");t1.start();t2.start();t3.start();}
}

结果正确。

在这里插入图片描述

相关文章:

多线程JUC(一)

目录 前言一、多线程的三种实现方式1.继承Thread类2.实现Runnable接口3.利用Callable接口和Future接口4.三种方式对比 二、常见的成员方法1.getName、setName、currentThread、sleep2.线程的优先级3.守护线程4.插入线程 三、线程安全1.线程的生命周期2.同步代码块3.同步方法4.l…...

夸父工具箱(安卓版) 手机超强工具箱

如今&#xff0c;人们的互联网活动日益频繁&#xff0c;导致手机内存即便频繁清理&#xff0c;也会莫名其妙地迅速填满&#xff0c;许多无用的垃圾信息悄然占据空间。那么&#xff0c;如何有效应对这一难题呢&#xff1f;答案就是今天新推出的这款工具软件&#xff0c;它能从根…...

2025系统架构师(一考就过):案例之五:典型架构、架构演化、人工智能、云计算、大数据

六、中间件技术、典型架构 ◆中间件:在一个分布式系统环境中处于操作系统和应用程序之间的软件&#xff0c;可以在不同的技术之间共享资源&#xff0c;将不同的操作系统、数据库、异构的网络环境以及若干应用结合成一个有机的协同工作整体。 ◆中间件位于客户机/服务器的操作系…...

【随手笔记】利尔达NB模组

1.名称 移芯EC6263GPP 参数 指令备注 利尔达上电输出 [2025-03-04 10:24:21.379] I_AT_WAIT:i_len2 [2025-03-04 10:24:21.724] LI_AT_WAIT:i_len16 [2025-03-04 10:24:21.724] [2025-03-04 10:24:21.733] Lierda [2025-03-04 10:24:21.733] [2025-03-04 10:24:21.745] OK移…...

Mybatis 中#{} 和${} 的区别是什么?

在 MyBatis 中&#xff0c;#{} 和 ${} 都是用于动态 SQL 语句中的占位符&#xff0c;但是它们的作用和使用方式是不同的。下面是它们的区别&#xff1a; 1. #{} —— 用于防止 SQL 注入和自动类型处理 #{} 是用来将参数安全地传递到 SQL 语句中&#xff0c;它会将传递的参数值…...

nginx+keepalived负载均衡及高可用

1 项目背景 keepalived除了能够管理LVS软件外&#xff0c;还可以作为其他服务的高可用解决方案软件。采用nginxkeepalived&#xff0c;它是一个高性能的服务器高可用或者热备解决方案&#xff0c;Keepalived主要来防止服务器单点故障的发生问题&#xff0c;可以通过其与Nginx的…...

数据结构理论

目录 基本概念和术语 数据 数据元素 数据项 数据对象 数据结构 数据的结构 逻辑结构 存储结构&#xff08;物理结构&#xff09; 数据类型 定义 原子数据类型 结构数据类型 抽象数据类型&#xff08;Abstract Data Type&#xff0c;ADT&#xff09; 算法和算法分…...

【心得】一文梳理高频面试题 HTTP 1.0/HTTP 1.1/HTTP 2.0/HTTP 3.0的区别并附加记忆方法

面试时很容易遇到的一个问题—— HTTP 1.0/HTTP 1.1/HTTP 2.0/HTTP 3.0的区别&#xff0c;其实这四个版本的发展实际上是一环扣一环的&#xff0c;是逐步完善的&#xff0c;本文希望帮助读者梳理清楚各个版本之间的区别&#xff0c;并且给出当前各个版本的应用情况&#xff0c;…...

在Spring Boot项目中导出复杂对象到Excel文件

在Spring Boot项目中导出复杂对象到Excel文件&#xff0c;可以利用Hutool或EasyExcel等库来简化操作。这里我们将详细介绍如何使用Hutool和EasyExcel两种方式来实现这一功能。 使用Hutool导出复杂对象到Excel 首先确保你的pom.xml中添加了Hutool的依赖&#xff1a; <depe…...

spark 常见操作命令

配置虚拟机 配置即让自己的虚拟机可以联网&#xff0c;和别的虚拟机通讯 一、配置vm虚拟机网段。 具体设置为&#xff1a;虚拟机左上角点击编辑→虚拟网络编辑器&#xfffc; 选择VMnet8&#xff0c; 要改动两个地方&#xff08;注意&#xff1a;它会需要管理员权限&#xff…...

深入理解设计模式中的工厂模式(Factory Pattern)

各类资料学习下载合集 ​​https://pan.quark.cn/s/8c91ccb5a474​​ 工厂模式是创建对象的一种设计模式,属于创建型设计模式。它提供了一种方法来创建对象,而无需在代码中直接指定对象的具体类。工厂模式通过将对象的创建过程封装起来,使得代码更加灵活、可维护…...

DPDK网络开发

DPDK&#xff08;Data Plane Development Kit&#xff09;是一个用于快速数据包处理的开源库&#xff0c;广泛应用于高性能网络应用开发。 环境准备 硬件要求 NIC&#xff08;网络接口卡&#xff09;&#xff1a;支持DPDK的网卡&#xff0c;如Intel的82599、X710等。 CPU&am…...

第三节:基于Winform框架的串口助手小项目---串口操作《C#编程》

知识是无尽的宝藏&#xff0c;学习的过程虽有挑战&#xff0c;但每一次突破都是对自我的升华&#xff0c;向着更优秀的自己全力进发。 -----------WHAPPY 本节将重点介绍&#xff0c;如何修改控件的属性、SerialPort类的使用及实现串口初始化的操作 1.修改控件属性 修改属性…...

机器学习核函数

在机器学习中&#xff0c;核函数&#xff08;Kernel Function&#xff09;是一个非常重要的概念&#xff0c;特别是在支持向量机&#xff08;SVM&#xff09;等算法中有着广泛的应用。下面从定义、作用、常见的核函数类型、工作原理等方面详细介绍&#xff1a; 定义&#xff1…...

linux中使用firewall命令操作端口

一、开放端口 1. 开放一个端口 sudo firewall-cmd --zonepublic --add-port8443/tcp --permanent sudo firewall-cmd --reload 2. 开放一组连续端口 sudo firewall-cmd --zonepublic --add-port100-500/tcp --permanent sudo firewall-cmd --reload 3. 一次开放多个不连续…...

【金融量化】Ptrade中的基础交易与高级量化交易策略的下单接口

1 基础交易与订单管理接口 1. order 功能&#xff1a;用于按指定数量买卖股票或其他金融产品。 参数&#xff1a; security&#xff1a;股票代码&#xff08;字符串类型&#xff09;。amount&#xff1a;交易数量&#xff08;整数类型&#xff09;&#xff0c;正数表示买入&…...

解决docker认证问题 failed to authorize: failed to fetch oauth token

报错信息[bash1]解决方案 全局代理打开“buildkit”: false &#xff0c;见[图1] [bash1] >docker build -t ffpg . [] Building 71.8s (3/3) FINISHED docker:desktop-linux> [internal] load bui…...

从“人力投放”到“智能战争”,谁能抢占先机?

流量成本飙升、用户行为碎片化、广告创意同质化……传统网络推广模式正面临失效危机。而AI技术的爆发&#xff0c;正在彻底改写游戏规则。小马识途营销顾问解析&#xff1a;“AI如何颠覆网络推广逻辑&#xff1f;企业又该如何借势破局&#xff1f;” 一、精准营销&#xff1a;…...

STM32_IIC外设工作流程

STM32 IC 外设工作流程&#xff08;基于寄存器&#xff09; 在 STM32 中&#xff0c;IC 通信主要通过一系列寄存器控制。理解这些寄存器的作用&#xff0c;能够帮助我们掌握 IC 硬件的运行机制&#xff0c;实现高效的数据传输。本文以 STM32F1&#xff08;如 STM32F103&#x…...

Python 爬取唐诗宋词三百首

你可以使用 requests 和 BeautifulSoup 来爬取《唐诗三百首》和《宋词三百首》的数据。以下是一个基本的 Python 爬虫示例&#xff0c;它从 中华诗词网 或类似的网站获取数据并保存为 JSON 文件。 import requests from bs4 import BeautifulSoup import json import time# 爬取…...

浅浅初识AI、AI大模型、AGI

前记&#xff1a;这里只是简单了解&#xff0c;后面有时间会专门来扩展和深入。 当前&#xff0c;人工智能&#xff08;AI&#xff09;及其细分领域&#xff08;如AI算法工程师、自然语言处理NLP、通用人工智能AGI&#xff09;的就业前景呈现高速增长态势&#xff0c;市场需求…...

Spring40种注解(下)!!

Spring Bean 注解 ComponentScan ComponentScan注解用于配置Spring需要扫描的被组件注解注释的类所在的包。 可以通过配置其basePackages属性或者value属性来配置需要扫描的包路径。value属性是basePackages的别名。 Component Component注解用于标注一个普通的组件类&#…...

DeepSeek 系列模型:论文精读《A Survey of DeepSeek Models》

引言&#xff1a;一篇快速了解 DeepSeek 系列的论文。我在翻译时加入了一些可以提高 “可读性” 的连词 ✅ NLP 研 2 选手的学习笔记 笔者简介&#xff1a;Wang Linyong&#xff0c;NPU&#xff0c;2023级&#xff0c;计算机技术 研究方向&#xff1a;文本生成、大语言模型 论文…...

LeetCode hot 100—环形链表 II

题目 给定一个链表的头节点 head &#xff0c;返回链表开始入环的第一个节点。 如果链表无环&#xff0c;则返回 null。 如果链表中有某个节点&#xff0c;可以通过连续跟踪 next 指针再次到达&#xff0c;则链表中存在环。 为了表示给定链表中的环&#xff0c;评测系统内部…...

【AI】【Unity】关于Unity接入DeepseekAPI遇到的坑

前言 由于deepseek网页端在白天日常抽风&#xff0c;无法正常的使用&#xff0c;所以调用API就成了目前最好的选择&#xff0c;尤其是Deepseek的API价格低得可怕&#xff0c;这不是和白送的一样吗&#xff01;然后使用过很多本地部署接入API的方式&#xff0c;例如Chatbox、Pa…...

计算机视觉算法实战——医学影像分割(主页有源码)

✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连 ✨ ✨个人主页欢迎您的访问 ✨期待您的三连✨ ​ ​​​ 1. 领域简介✨✨ 医学影像分割是计算机视觉在医疗领域的重要应用&#xff0c;旨在从CT、MRI、X光等医学图像中精确分割出目标区域&…...

51单片机——存储类型

主要内容&#xff1a;区分data,bdata,idata,pdata,xdata,code 8051系列单片机存储器结构的特点&#xff1a;ROM和RAM独立编址 8051系列单片机将程序存储器&#xff08;ROM&#xff09;和数据存储器&#xff08;RAM&#xff09;分开&#xff0c;并有各自的寻址机构和寻址方式。…...

python19-if和match的美

课程&#xff1a;B站大学 记录python学习&#xff0c;直到学会基本的爬虫&#xff0c;使用python搭建接口自动化测试就算学会了&#xff0c;在进阶webui自动化&#xff0c;app自动化 分支语句那些事儿 if 条件判断if...else 判断语句if...elif...else 多重条件分支嵌套也能在 e…...

期权有哪些用处?期权和期货比优势在哪?

期权如同金融市场的“瑞士军刀”&#xff0c;既能防御风险&#xff0c;又能主动出击。相较于期货的“刚性对决”&#xff0c;期权更像“柔性博弈”——通过策略组合在不确定性中捕捉确定性收益。 期权有哪些用处&#xff1f; 期权的核心价值在于其非对称性——买方风险有限&am…...

【html期末作业网页设计】

html期末作业网页设计 作者有话说项目功能介绍 网站结构完整代码网站样图 作者有话说 目前&#xff0c;我们的项目已经搭建了各页面的基本框架&#xff0c;但内容填充还不完善&#xff0c;各页面之间的跳转逻辑也还需要进一步优化。 我们深知&#xff0c;一个好的项目需要不断…...

ComfyUI AnimeDiff动画参数总结

ComfyUI AnimeDiff动画参数总结 一、动画生成核心参数 参数名称建议值/范围作用说明备注步数&#xff08;Steps&#xff09;15-25控制AI计算迭代次数&#xff0c;越高细节越精细&#xff0c;但耗时更长推荐20步&#xff0c;显存不足可降至15步CFG值7.0-8.5提示词对画面的控制…...

基于Three.js的多视图3D Tiles同步可视化技术解析

文章目录 基于Three.js的多视图3D Tiles同步可视化技术解析一、技术背景与价值二、核心实现原理2.1 视口分割算法2.2 视角同步机制三、关键代码解析3.1 渲染管线优化3.2 3D Tiles加载四、交互系统实现4.1 多视图事件分发4.2 射线拾取优化五、性能优化方案5.1 渲染性能指标5.2 W…...

7、什么是死锁,如何避免死锁?【高频】

&#xff08;1&#xff09;什么是死锁&#xff1a; 死锁 是指在两个或多个进程的执行时&#xff0c;每个进程都持有资源&#xff0c;并都在等待其他进程 释放 它所需的资源&#xff0c;如果此时所有的进程一直占有资源而不释放&#xff0c;就导致了死锁。 死锁只有同时满足 四…...

自动化学习-使用git进行版本管理

目录 一、为什么要学习git 二、git是什么 三、git如何使用 1、git的下载安装和配置 2、git常用的命令 3、gitee远程仓库的使用 &#xff08;1&#xff09;注册 &#xff08;2&#xff09;创建仓库 &#xff08;3&#xff09;配置公钥&#xff08;建立电脑和git…...

前端大文件上传

一、切片上传技术原理 切片上传是把大文件分割成多个较小的切片&#xff0c;分别上传这些切片&#xff0c;最后在服务器端将它们合并成完整文件。这种方式能有效应对网络不稳定导致的上传失败问题&#xff0c;还可利用多线程并行上传&#xff0c;提升上传效率。 二、前端实现…...

【网络】实现电脑与笔记本电脑之间的直接网络连接

要实现电脑与笔记本电脑之间的直接网络连接&#xff0c;可以通过有线或无线两种方式。以下是详细的步骤指南&#xff1a; 一、有线直连&#xff08;通过网线&#xff09; 1. 准备工具 网线&#xff1a;使用交叉网线&#xff08;适用于旧设备&#xff09;或普通直连网线&#…...

“深入浅出”系列之音视频开发:(12)使用FFmpeg实现倍速播放:技术细节与优化思路

一、前言 在音视频处理领域&#xff0c;倍速播放是一个常见的需求&#xff0c;尤其是在视频播放器、在线教育平台等场景中&#xff0c;用户常常需要以不同的速度播放视频内容。然而&#xff0c;实现一个高质量的倍速播放功能并不容易&#xff0c;尤其是在处理音频时&#xff0…...

qt作业day2

1&#xff1a;在注册登录的练习里面&#xff0c;追加一个QListWidget 项目列表 要求&#xff1a;点击注册之后&#xff0c;将账号显示到 listWidget上面去 以及&#xff0c;在listWidget中双击某个账号的时候&#xff0c;将该账号删除 .h #ifndef WIDGET_H #define WIDGET_H …...

Qt:day1

一、作业 写1个Widget窗口&#xff0c;窗口里面放1个按钮&#xff0c;按钮随便叫什么&#xff1b; 创建2个Widget对象&#xff1a; Widget w1, w2; w1.show(); w2不管&#xff1b; 要求&#xff1a; 点击 w1.btn&#xff0c;w1隐藏&#xff0c;w2显示&#xff1b; 点击 w2.btn&…...

基于微信小程序的停车场管理系统的设计与实现

第1章 绪论 1.1 课题背景 随着移动互联形式的不断发展&#xff0c;各行各业都在摸索移动互联对本行业的改变&#xff0c;不断的尝试开发出适合于本行业或者本公司的APP。但是这样一来用户的手机上就需要安装各种软件&#xff0c;但是APP作为一个只为某个公司服务的一个软件&a…...

详细Linux基础知识(不断完善)

终端类型分类 1. 物理终端 直接连接到计算机的硬件设备2. 虚拟终端 通过快捷键切换的文本模式界面: Ctrl + Alt + F1 # 登录窗口 Ctrl + Alt + F2 # 当前图形界面 Ctrl + Alt + F3 # 虚拟命令终端 Ctrl + Alt + F4-F6 # 备用虚拟终端3. 图形终端 模拟终端:图形环境中的…...

类和对象-继承-C++

1.定义 面向对象的三大特征之一&#xff0c;为了减少重复的代码 2.语法 class 子类 &#xff1a;继承方式 父类 &#xff08;子类也叫派生类&#xff0c;父类也称为基类&#xff09; 例&#xff1a;class age&#xff1a;public person&#xff1b; #include<iostrea…...

初阶数据结构(C语言实现)——3顺序表和链表(1)

目录 【本节目标】1. 线性表2.顺序表2.1概念及结构2.2 接口实现2.2.0 动态顺序表2.2.1 顺序表初始化SLInit&#xff08;&#xff09;2.2.2 销毁和打印2.2.3 尾插SLPushBack&#xff08;&#xff09;2.2.4 尾删SLPopBack&#xff08;&#xff09;2.2.5 头插2.2.6 头删2.2.7 插入…...

nuxt常用组件库html-validator、@nuxtjs/i18n、@nuxt/image、@unocss/nuxt使用解析

html-validator 主要用于自动验证nuxt服务器呈现的HTML(SSR和SSG)&#xff0c;以检测可能导致水合错误的HTML常见问题&#xff0c;有助于减少水合错误&#xff0c;检测常见的可访问性错误。 安装 npx nuxilatest module add html-validator配置 若自动更新nuxt.config.ts配置文…...

4G工业路由器在公交充电桩中的应用与优势

随着电动公交车的普及&#xff0c;公交充电桩的稳定运行和高效管理是交通营运部门最关心的问题。4G工业路由器凭借其卓越的数据采集和通讯能力&#xff0c;成为实现充电桩智能化管理的关键。 公交充电桩运维管理需求概述&#xff1a; 1.实时性&#xff1a;实时监控充电状态、剩…...

matlab 四维数据可视化(已解决)

虽然这不是传统意义上的“4维可视化”&#xff0c;但你可以通过在三维空间中表示两个维度来间接展示4维数据。例如&#xff0c;你可以使用颜色来表示第四个维度。 clc clear close all% 假设X, Y, Z为你的三维数据&#xff0c;C为第四维数据 X rand(100, 1); Y rand(100, 1);…...

歌曲分类和流行度预测

1. 项目介绍 本项目从kaggle平台上下载了数据集&#xff0c;该数据集包含了3万多首来自Spotify API 的歌曲&#xff0c;共有23个特征。首先对数据集进行预处理&#xff0c;如重复行、缺失值、标准化处理等。再对预处理后的数据进行探索性分析&#xff0c;观察各变量的分布情况&…...

经验分享:用一张表解决并发冲突!数据库事务锁的核心实现逻辑

背景 对于一些内部使用的管理系统来说&#xff0c;可能没有引入Redis&#xff0c;又想基于现有的基础设施处理并发问题&#xff0c;而数据库是每个应用都避不开的基础设施之一&#xff0c;因此分享个我曾经维护过的一个系统中&#xff0c;使用数据库表来实现事务锁的方式。 之…...

oracle decode

1. 基本语法 DECODE(expression, search1, result1, search2, result2, ..., default_result) expression &#xff1a;需要比较的表达式或列。search1, search2, ... &#xff1a;要匹配的值。result1, result2, ... &#xff1a;当 expression 等于 search 时返回的结果。def…...

让后台界面布局更灵活:在GrapesJS中复刻Java的五区式布局

当你想要在可视化编辑器中做一个类似Java BorderLayout 的五区布局&#xff0c;却发现市面上大多只能“简单拼接”而难以自由扩展时&#xff0c;你或许就需要一个更灵活的布局管理器来帮忙。本篇文章就从这个痛点开始&#xff0c;带你一步步揭秘如何用 GrapesJS 自定义并实现一…...