线程的基本概念
文章目录
- 基础概念
- 线程与进程
- 什么是进程?
- 什么是线程?
- 进程和线程的区别:
- 多线程
- 什么是多线程?
- 多线程的局限性
- 串行、并行、并发
- 同步异步、阻塞非阻塞
- 线程的创建
- 1、继承Thread类,重写run方法
- 2、实现Runnable接口,重写run方法
- 3、实现Callable,重写call方法,配合FutureTask
- 4、基于线程池构建线程 ExecutorService
- 线程的使用
- 线程的状态
- 线程的常用方法
- 获取当前线程Thread.currentThread()
- 线程的名字getName()
- 线程的优先级Thread.getPriority()
- 线程的让步Thread.yield()
- 线程的休眠Thread.sleep()
- 线程的强占Thread.join()
- 守护线程Daemon
- 线程的等待和唤醒 Object.wait()&Object.notify()
- 线程的结束方式
- stop方法(不用)
- 使用共享变量(很少用)
- interrupt方式
- wait和sleep的区别?
基础概念
线程与进程
什么是进程?
进程是指运行中的程序。 比如我们使用钉钉浏、览器等,启动这个程序时操作系统会给这个程序分配一定的资源(占用内存资源)。
什么是线程?
线程是CPU调度的基本单位,每个线程执行的都是某一个进程的代码的某个片段。
所谓进程就是线程的容器,需要线程利用进程中的一些资源,处理一个代码、指令,最终实现进程所预期的结果。
进程和线程的区别:
- 根本不同:进程是操作系统分配的资源,而线程是CPU调度的基本单位。
- 资源方面:同一个进程下的线程共享进程中的一些资源。线程同时拥有自身的独立存储空间。进程之间的资源通常是独立的。
- 数量不同:进程一般指的就是一个进程。而线程是依附于某个进程的,而且一个进程中至少会有一个或多个线程。
- 开销不同:毕竟进程和线程不是一个级别的内容,线程的创建和终止的时间是比较短的。而且线程之间的切换比进程之间的切换速度要快很多。而且进程之间的通讯很麻烦,一般要借助内核才可以实现,而线程之间通讯相当方面。
- … …
多线程
什么是多线程?
多线程是指:单个进程下同时运行的多个线程。
多线程的目的是为了提高CPU的利用率。
可以通过避免一些网络IO或者磁盘IO等需要等待的操作,让CPU去调度其他线程。这样可以大幅度的提升程序的效率,提高用户的体验。比如Tomcat可以做并行处理,提升处理的效率,而不是一个一个排队。比如要处理一个网络等待的操作,开启一个线程去处理需要网络等待的任务,让当前业务线程可以继续往下执行逻辑,效率是可以得到大幅度提升的。
多线程的局限性
- 如果线程数量特别多,CPU在切换线程上下文时,会额外造成很大的消耗。
- 任务的拆分需要依赖业务场景,有一些异构化的任务,很难对任务拆分,还有很多业务并不是多线程处理更好。
- 线程安全问题:虽然多线程带来了一定的性能提升,但是再做一些操作时,多线程如果操作临界资源,可能会发生一些数据不一致的安全问题,甚至涉及到锁操作时,会造成死锁问题。
串行、并行、并发
串行就是一个一个排队,第一个做完,第二个才能上。
并行就是同时处理。
这里的并发并不是三高中的高并发问题,这里是多线程中的并发概念(CPU调度线程的概念)。 CPU在极短的时间内,反复切换执行不同的线程,看似好像是并行,但是只是CPU高速的切换。
并行囊括并发。并行就是多核CPU同时调度多个线程,是真正的多个线程同时执行。单核CPU无法实现并行效果,单核CPU是并发。
同步异步、阻塞非阻塞
同步与异步:执行某个功能后,被调用者是否会主动反馈信息
阻塞和非阻塞:执行某个功能后,调用者是否需要一直等待结果的反馈。
两个概念看似相似,但是侧重点是完全不一样的。
同步阻塞:比如用锅烧水,水开后,不会主动通知你。烧水开始执行后,需要一直等待水烧开。
同步非阻塞:比如用锅烧水,水开后,不会主动通知你。烧水开始执行后,不需要一直等待水烧开,可以去执行其他功能,但是需要时不时的查看水开了没。
异步阻塞:比如用水壶烧水,水开后,会主动通知你水烧开了。烧水开始执行后,需要一直等待水烧开。
异步非阻塞:比如用水壶烧水,水开后,会主动通知你水烧开了。烧水开始执行后,不需要一直等待水烧开,可以去执行其他功能。
异步非阻塞这个效果是最好的,平时开发时,提升效率最好的方式就是采用异步非阻塞的方式处理一些多线程的任务。
线程的创建
创建线程的几种方式:
1、继承Thread类,重写run方法
启动线程是调用start方法,这样会创建一个新的线程,并执行线程的任务。
如果直接调用run方法,这样会让当前线程执行run方法中的业务逻辑。
static class MyThread extends Thread {@Overridepublic void run() {System.out.println("Hello MyThread!");}
}
2、实现Runnable接口,重写run方法
static class MyRun implements Runnable {@Overridepublic void run() {System.out.println("Hello MyRun!");}
}
// 最常用的两种方式:
public void myRunMethod(){// 匿名内部类方式:Thread thread1 = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("MyRunnable!");}});// lamdba方式:Thread thread2 = new Thread(()->{System.out.println("MyRunnable!");});
}
3、实现Callable,重写call方法,配合FutureTask
Callable一般用于有返回结果的非阻塞的执行方法。同步非阻塞。
static class MyCall implements Callable<String> {@Overridepublic String call() throws Exception {System.out.println("Hello MyCall!");return "success";}
}
4、基于线程池构建线程 ExecutorService
public class HowToCreateThread {// 启动线程的几种方式public static void main(String[] args) {new MyThread().start();new Thread(new MyRun()).start();new Thread(() -> {System.out.println("Hello Lambda!");}).start();Thread t = new Thread(new FutureTask<String>(new MyCall()));t.start();ExecutorService service = Executors.newCachedThreadPool();service.execute(() -> {System.out.println("Hello ThreadPool!");});service.shutdown();}
}
注:追其底层,其实只有一种,实现Runnable。
线程的使用
线程的状态
网上对线程状态的描述有很多,有5种、6种、7种,都可以接受。
5种状态一般针对传统的线程状态来说的(操作系统层面的)

Java中给线程定义的是6种状态。

- NEW:Thread对象被创建出来了,但是还没有执行start方法。
- RUNNABLE: Thread对象调用了start方法,就为RUNNABLE状态(CPU调度/没有调度)
- BLOCKED:synchronized没有拿到同步锁,被阻塞的情况。
- WAITING:调用wait方法就会处于WAITING状态,需要被手动唤醒。
- TIME_WAITING:调用sleep方法或者join方法,会被自动唤醒,无需手动唤醒。
- TERMINATED:run方法执行完毕,线程生命周期结束。
BLOCKED、WAITING、TIME_WAITING都可以理解为是阻塞、等待状态,因为处在这三种状态下,CPU不会调度当前线程。
下面在Java代码中验证一下具体效果:
public static void main(String[] args) throws InterruptedException {// NEWThread t1 = new Thread();System.out.println(t1.getState());// RUNNABLEThread t2 = new Thread(() -> {while (true) {}});t2.start();Thread.sleep(500);System.out.println(t2.getState());// BLOCKEDObject obj3 = new Object();Thread t3 = new Thread(() -> {// t3线程拿不到锁资源,导致变为BLOCKED状态synchronized (obj3) {}});// main线程拿到obj的锁资源synchronized (obj3) {t3.start();Thread.sleep(500);System.out.println(t3.getState());}// WAITINGObject obj4 = new Object();Thread t4 = new Thread(() -> {synchronized (obj4) {try {obj4.wait();} catch (InterruptedException e) {e.printStackTrace();}}});t4.start();Thread.sleep(500);System.out.println(t4.getState());// TIMED_WAITINGThread t5 = new Thread(() -> {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}});t5.start();Thread.sleep(500);System.out.println(t5.getState());// TERMINATEDThread t6 = new Thread(() -> {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}});t6.start();Thread.sleep(1000);System.out.println(t6.getState());
}
线程的常用方法
获取当前线程Thread.currentThread()
Thread的静态方法获取当前线程对象。
public static void main(String[] args) {// 获取当前线程的方法Thread main = Thread.currentThread();System.out.println(main);// Thread[#1,main,5,main]// "Thread[" + getName() + "," + getPriority() + "," + group.getName() + "]";
}
线程的名字getName()
在构建Thread对象完毕后,一定要设置一个有意义的名称,方面后期排查错误。
public static void main(String[] args) {Thread t1 = new Thread(() -> {System.out.println(Thread.currentThread().getName());});t1.setName("模块-功能-计数器");t1.start();
}
线程的优先级Thread.getPriority()
其实就是CPU调度线程的优先级。 Java中给线程设置的优先级别有10个级别,从1~10任取一个整数。 如果超出这个范围,会排除参数异常的错误。
public static void main(String[] args) {Thread t1 = new Thread(() -> {for (int i = 0; i < 100; i++) {System.out.println("t1:"+i);}});Thread t2 = new Thread(() -> {for (int i = 0; i < 200; i++) {System.out.println("t2:"+i);}});t1.setPriority(1);t2.setPriority(10);t2.start();t1.start();
}
线程的让步Thread.yield()
可以通过Thread的静态方法yield,让当前线程从运行状态转变为就绪状态。
public static void main(String[] args) {Thread t1 = new Thread(() -> {for (int i = 0; i < 100; i++) {if (i == 50) {Thread.yield();}System.out.println("t1:" + i);}});Thread t2 = new Thread(() -> {for (int i = 0; i < 100; i++) {System.out.println("t2:" + i);}});t2.start();t1.start();
}
线程的休眠Thread.sleep()
Thread的静态方法,让线程从运行状态转变为等待状态。
sleep有两个方法重载:
- 第一个就是native修饰的,让线程转为等待状态的效果
- 第二个是可以传入毫秒和一个纳秒的方法(如果纳秒值大于等于0.5毫秒,就给休眠的毫秒值 +1。如果传入的毫秒值是0,纳秒值不为0,就休眠1毫秒)
sleep会抛出一个InterruptedException
public static void main(String[] args) throws InterruptedException {System.out.println(System.currentTimeMillis());Thread.sleep(1000);System.out.println(System.currentTimeMillis());
}
线程的强占Thread.join()
Thread的非静态方法join方法。需要在某一个线程下去调用这个方法。
如果在main线程中调用了t1.join(),那么main线程会进入到等待状态,需要等待t1线程全部执行完毕,再恢复到就绪状态等待CPU调度。
如果在main线程中调用了t1.join(2000),那么main线程会进入到等待状态,需要等待t1执行2s后, 再恢复到就绪状态等待CPU调度。如果在等待期间,t1已经结束了,那么main线程自动变为就绪状态等待CPU调度。
public static void main(String[] args) {Thread t1 = new Thread(() -> {for (int i = 0; i < 10; i++) {System.out.println("t1:" + i);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t1.start();for (int i = 0; i < 10; i++) {System.out.println("main:" + i);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}if (i == 1) {try {t1.join(2000);} catch (InterruptedException e) {e.printStackTrace();}}}
}
守护线程Daemon
默认情况下,线程都是非守护线程。
JVM会在程序中没有非守护线程时,结束掉当前JVM。
主线程默认是非守护线程,如果主线程执行结束,需要查看当前JVM内是否还有非守护线程,如果没有JVM直接停止。
public static void main(String[] args) {Thread t1 = new Thread(() -> {for (int i = 0; i < 10; i++) {System.out.println("t1:" + i);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});t1.setDaemon(true);t1.start();
}
线程的等待和唤醒 Object.wait()&Object.notify()
可以让获取synchronized锁资源的线程通过wait方法进去到锁的等待池,并且会释放锁资源。
可以让获取synchronized锁资源的线程,通过notify或者notifyAll方法,将等待池中的线程唤醒,添加到锁池中。
notify随机的唤醒等待池中的一个线程到锁池。
notifyAll将等待池中的全部线程都唤醒,并且添加到锁池。
在调用wait方法和notify以及norifyAll方法时,必须在synchronized修饰的代码块或者方法内部才可以,因为要操作基于某个对象的锁的信息维护。
public class MiTest {public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {sync();}, "t1");Thread t2 = new Thread(() -> {sync();}, "t2");t1.start();t2.start();Thread.sleep(12000);synchronized (MiTest.class) {MiTest.class.notifyAll();}}public static synchronized void sync() {try {for (int i = 0; i < 10; i++) {if (i == 5) {MiTest.class.wait();}Thread.sleep(1000);System.out.println(Thread.currentThread().getName());}} catch (InterruptedException e) {e.printStackTrace();}}
}
线程的结束方式
线程结束方式很多,最常用就是让线程的run方法结束。无论是return结束,还是抛出异常结束都可以。
stop方法(不用)
强制让线程结束,无论你在干嘛,不推荐使用。但是,他确实可以把线程干掉。
public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}});t1.start();Thread.sleep(500);t1.stop();System.out.println(t1.getState());
}
使用共享变量(很少用)
这种方式用的也不多,有的线程可能会通过死循环来保证一直运行。
可以通过修改共享变量在破坏死循环,让线程退出循环,结束run方法。
static volatile boolean flag = true;public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {while (flag) {// 处理任务}System.out.println("任务结束");});t1.start();Thread.sleep(500);flag = false;
}
interrupt方式
共享变量方式。
public static void main(String[] args) throws InterruptedException {// 线程默认情况下, interrupt标记位:falseSystem.out.println(Thread.currentThread().isInterrupted());// 执行interrupt之后,再次查看打断信息Thread.currentThread().interrupt();// interrupt标记位:tureSystem.out.println(Thread.currentThread().isInterrupted());// 返回当前线程,并归位为false interrupt标记位:tureSystem.out.println(Thread.interrupted());// 已经归位了System.out.println(Thread.interrupted());// =====================================================Thread t1 = new Thread(() -> {while (!Thread.currentThread().isInterrupted()) { // 处理业务}System.out.println("t1结束");});t1.start();Thread.sleep(500);t1.interrupt();
}
通过打断WAITING或者TIMED_WAITING状态的线程,从而抛出异常自行处理。这种停止线程方式是最常用的一种,在框架和JUC中也是最常见的。
public static void main(String[] args) throws InterruptedException {Thread t1 = new Thread(() -> {while (true) {// 获取任务// 拿到任务,执行任务// 没有任务了,让线程休眠try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();System.out.println("基于打断形式结束当前线程");return;}}});t1.start();Thread.sleep(500);t1.interrupt();
}
wait和sleep的区别?
- 单词不一样
- sleep属于Thread类中的static方法,wait属于Object类的方法。
- sleep属于TIMED_WAITING,自动唤醒;wait属于WAITING,需要手动唤醒。
- sleep方法在持有锁时,执行,不会释放资源。wait在执行后,会释放锁资源。
- sleep方法可以在持有锁或者不持有锁执行。wait方法必须在持有锁的时才能执行。
wait方法会将持有锁的线程从owner扔到waitSet集合中,这个操作是在修改ObjectMointor对象,如果没有持有synchronized锁的话,是无法操作ObjectMointor的。
相关文章:
线程的基本概念
文章目录基础概念线程与进程什么是进程?什么是线程?进程和线程的区别:多线程什么是多线程?多线程的局限性串行、并行、并发同步异步、阻塞非阻塞线程的创建1、继承Thread类,重写run方法2、实现Runnable接口,…...
java面试题中常见名词注解
一.常见名词注解 1.mysql索引,索引数据结构,hash,二叉树,B树,B树,红黑树, mysql索引:帮助mysql高效获取数据的数据结构,通俗来说,数据库索引就好比一本书的…...
SpringAOP从入门到源码分析大全,学好AOP这一篇就够了(二)
文章目录系列文档索引四、Spring AOP的使用入门1、激活AspectJ模块(1)注解激活(2)XML激活2、创建 AspectJ 代理(了解)(1)编程方式创建 AspectJ 代理实例(2)XM…...
华为OD机试 - 斗地主(C++) | 附带编码思路 【2023】
刷算法题之前必看 参加华为od机试,一定要注意不要完全背诵代码,需要理解之后模仿写出,通过率才会高。 华为 OD 清单查看地址:https://blog.csdn.net/hihell/category_12199283.html 华为OD详细说明:https://dream.blog.csdn.net/article/details/128980730 华为OD机试题…...
【存储】etcd的存储是如何实现的(3)-blotdb
前两篇分别介绍了etcd的存储模块以及mvcc模块。在存储模块中,提到了etcd kv存储backend是基于boltdb实现的,其在boltdb的基础上封装了读写事务,通过内存缓存批量将事务刷盘,提升整体的写入性能。botldb是etcd的真正的底层存储。本…...
基于MATLAB开发AUTOSAR软件应用层模块-part21.SR interface通信介绍(包括isupdated判断通信)
这篇文章我们介绍最后一种interface,即Sender-Receiver Interface,这种通信方式是autosar架构中最常用的的通信方式,即一个SWC发送数据,另一个SWC接收数据,实现数据交互。下边我们介绍下这篇文章主要介绍的内容: 目录如下: 如何配置SR interface,实现SR 通信介绍含有…...
Kotlin新手教程八(泛型)
一、泛型 1.泛型类的创建与实例化 kotlin中泛型类的创建与实例化与Java中相似: class A<T>(t:T){var valuet }fun main() {var a:A<Int> A<Int>(11) }Kotlin中存在类型推断,所以创建实例可以写成: var aA(11)2.泛型约束…...
性能测试知多少?怎样开展性能测试
看到好多新手,在性能需求模糊的情况下,随便找一个性能测试工具,然后就开始进行性能测试了,在这种情况下得到的性能测试结果很难体现系统真实的能力,或者可能与系统真实的性能相距甚远。 与功能测试相比,性能…...
code-breaking之javacon
JAVACON 题目 此题 来自P神 的code-breaking中的一道Java题,名为javacon,题目知识点为SpEL注入 题目下载地址:https://www.leavesongs.com/media/attachment/2018/11/23/challenge-0.0.1-SNAPSHOT.jar 运行环境 java -jar challenge-0.…...
Android 字符串替换,去除空格等操作
今天在写代码的时候,需要对String进行一些操作,例如变小写,去除所有空格 于是熟练的使用String的replaceAll,却发现没这个方法。 后面才发现Kotlin使用的是自己的String,有自己的方法,用String的replace(…...
因“AI”而“深” 第四届OpenI/O 启智开发者大会高校开源专场25日开启!
中国算力网资源不断开发,开源社区治理及AI开源生态引来众多有才之士参与建设,国家级开放创新应用平台、NLP大模型等高新技术内容逐渐走向科研舞台上聚光灯的中心,新时代的大门缓缓打开。在启智社区,有一群人,他们年纪轻…...
CATCTF wife原型链污染
CATCTF wife原型链污染 原型链污染原理:https://drun1baby.github.io/2022/12/29/JavaScript-%E5%8E%9F%E5%9E%8B%E9%93%BE%E6%B1%A1%E6%9F%93/ 如下代码,prototype是newClass类的一个属性。newClass 实例化的对象 newObj 的 .__proto__ 指向 newClass…...
浅谈Java线程池中的ThreadPoolExecutor工具类
目录 ThreadPoolExecutor的构造函数 关于线程池的一些补充 线程池运行原理分析 概念原理解释 整个流程图如下: 一点补充 创建线程池主要有两种方式: 通过Executor工厂类创建,创建方式比较简单,但是定制能力有限通过ThreadPoo…...
分析过程:服务器被黑安装Linux RootKit木马
前言 疫情还没有结束,放假只能猫家里继续分析和研究最新的攻击技术和样本了,正好前段时间群里有人说服务器被黑,然后扔了个样本在群里,今天咱就拿这个样本开刀, 给大家研究一下这个样本究竟是个啥,顺便也给…...
运动型蓝牙耳机推荐哪款、最新运动蓝牙耳机推荐
提起运动耳机,如今很多运动爱好者和职业教练员们,都会向萌新推荐骨传导运动耳机。骨传导耳机解决了入耳式蓝牙耳机掉落的问题,佩戴相当舒服。骨传导耳机在佩戴过程中解放了双耳,不会因为耳机堵住耳朵,听不到环境音&…...
Python爬虫(9)selenium爬虫后数据,存入mongodb实现增删改查
之前的文章有关于更多操作方式详细解答,本篇基于前面的知识点进行操作,如果不了解可以先看之前的文章 Python爬虫(1)一次性搞定Selenium(新版)8种find_element元素定位方式 Python爬虫(2)-Selenium控制浏览…...
gulimall技术栈笔记
文章目录1.项目背景1.1电商模式1.2谷粒商城2.项目架构图3.项目技术&特色4.项目前置要求5.分布式基础概念5.1微服务5.2集群&分布式&节点5.3远程调用5.4负载均衡5.5服务注册/发现&注册中心5.6配置中心5.7服务熔断&服务降级5.7.1服务熔断5.7.2服务降级5.8API网…...
vue3生命周期钩子以及使用方式
按照生命周期的顺序来排列: onBeforeMount() DOM挂载前调用 注册一个钩子,在组件被挂载之前被调用。 当这个钩子被调用时,组件已经完成了其响应式状态的设置,但还没有创建 DOM 节点。它即将首次执行 DOM 渲染过程。 onMount(…...
以假乱真的手写模拟器?
前些时候给大家推荐了一款word插件叫做“不坑盒子”,这款盒子不仅方便了word的操作,还附带了手写模拟器这样的效果只是在使用的时候不仅需要手动下载字体,而且效果也并不是太理想。 今天小编找到了一款软件--手写模拟器,不仅一键生…...
每日一题——L1-069 胎压监测(15)
L1-069 胎压监测 分数 15 小轿车中有一个系统随时监测四个车轮的胎压,如果四轮胎压不是很平衡,则可能对行车造成严重的影响。 让我们把四个车轮 —— 左前轮、右前轮、右后轮、左后轮 —— 顺次编号为 1、2、3、4。本题就请你编写一个监测程序&#…...
C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】
微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来,Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...
中南大学无人机智能体的全面评估!BEDI:用于评估无人机上具身智能体的综合性基准测试
作者:Mingning Guo, Mengwei Wu, Jiarun He, Shaoxian Li, Haifeng Li, Chao Tao单位:中南大学地球科学与信息物理学院论文标题:BEDI: A Comprehensive Benchmark for Evaluating Embodied Agents on UAVs论文链接:https://arxiv.…...
【Web 进阶篇】优雅的接口设计:统一响应、全局异常处理与参数校验
系列回顾: 在上一篇中,我们成功地为应用集成了数据库,并使用 Spring Data JPA 实现了基本的 CRUD API。我们的应用现在能“记忆”数据了!但是,如果你仔细审视那些 API,会发现它们还很“粗糙”:有…...
微信小程序云开发平台MySQL的连接方式
注:微信小程序云开发平台指的是腾讯云开发 先给结论:微信小程序云开发平台的MySQL,无法通过获取数据库连接信息的方式进行连接,连接只能通过云开发的SDK连接,具体要参考官方文档: 为什么? 因为…...
项目部署到Linux上时遇到的错误(Redis,MySQL,无法正确连接,地址占用问题)
Redis无法正确连接 在运行jar包时出现了这样的错误 查询得知问题核心在于Redis连接失败,具体原因是客户端发送了密码认证请求,但Redis服务器未设置密码 1.为Redis设置密码(匹配客户端配置) 步骤: 1).修…...
视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...
Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战
说明:这是一个机器学习实战项目(附带数据代码文档),如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下,风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...
【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...
虚拟电厂发展三大趋势:市场化、技术主导、车网互联
市场化:从政策驱动到多元盈利 政策全面赋能 2025年4月,国家发改委、能源局发布《关于加快推进虚拟电厂发展的指导意见》,首次明确虚拟电厂为“独立市场主体”,提出硬性目标:2027年全国调节能力≥2000万千瓦࿰…...
