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

关于Java多线程的那些事

多线程

  • 多线程
    • 1. 关于多线程的理解
      • 1.1 进程和线程
      • 1.2 并行和并发
      • 1.3 线程调度
    • 2. 创建多线程的方式
      • 创建线程有哪几种方式?
        • 2.1 通过继承`Thread`类来创建并启动线程的步骤如下:
        • 2.2 通过实现`Runnable`接口来创建并启动线程的步骤如下:
        • 2.3 通过实现`Callable`接口来创建并启动线程的步骤如下:
    • 3 run()和start()有什么区别?
    • 4 线程是否可以重复启动,会有什么后果?
    • 5. 说一说sleep()和wait()的区别
    • 6. 说一说notify()、notifyAll()的区别
    • 7. 如何实现子线程先执行,主线程再执行?
    • 8. Thread 类的方法
      • 8.1 构造方法
      • 8.2 Thread 类的常用方法

多线程

1. 关于多线程的理解

1.1 进程和线程

每个进程有多个线程

  • 进程是系统运行程序的基本单元
  • 每个进程的内部数据和状态是完全独立的
  • 每一个应用程序运行的时候会产生一个进程
  • 线程:就是一个进程中的执行单元。一个进程可以启动多个线程。cpu 调度和分配的最小单元。
  • 线程必须在某个进程内执行。

所以多线程就是:在一个进程中同时运行了多个线程,用来完成不同的工作,则称之为多线程。

  • 进程与线程的区别
    • 进程:有独立的内存空间,进程中的数据存放空间(堆空间和栈空间)是独立的,至少
      有一个线程。
    • 线程:堆空间是共享的,栈空间是独立的,线程消耗的资源比进程小的多。

1.2 并行和并发

  1. 并发(Concurrency)

    • 并发是指多个任务在相同的时间段内交替执行,每个任务可能只执行一小部分,然后切换到另一个任务。
    • 并发并不一定意味着多个任务同时在不同的处理器核心上执行。它可以在单个处理器上通过时间片轮转来实现,也可以在多个处理器核心上并行执行。
    • 通常,多线程程序是并发的,因为它们可以在单个处理器上通过线程切换实现并发执行。

    示例:多个线程在单个处理器上轮流执行,共享CPU时间。

  2. 并行(Parallelism)

    • 并行是指多个任务在相同的时间点上同时执行,每个任务都在不同的处理器核心上运行。
    • 并行通常需要多核处理器或多个计算资源,并且可以实现更高的性能,因为多个任务可以在不互相干扰的情况下并行执行。
    • 并行通常用于解决需要高性能的问题,如大规模数据处理或计算密集型任务。

    示例:多个线程在不同的处理器核心上同时执行,各自独立工作。

总结:

  • 并发是任务在时间上交替执行,可能在同一处理器核心上通过线程切换实现。
  • 并行是任务在同一时刻同时执行,通常需要多个处理器核心或多个计算资源来实现。
  • 并发可以提高系统的响应性和资源利用率,但并不一定提高吞吐量。
  • 并行通常用于提高性能,特别是在多核处理器上,可以实现更高的吞吐量

1.3 线程调度

每个程序至少自动拥有一个线程,称为主线程

  1. 分时调度
    所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间。

  2. 抢占式调度

    优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性), Java 使用的为抢占式调度。

2. 创建多线程的方式

创建线程有哪几种方式?

创建线程有三种方式,分别是继承Thread类、实现Runnable接口、实现Callable接口

2.1 通过继承Thread类来创建并启动线程的步骤如下:

  1. 定义Thread类的子类,并重写该类的run()方法,该run()方法将作为线程执行体。

  2. 创建Thread子类的实例,即创建了线程对象

  3. 调用线程对象的start()方法来启动该线程。

/*** 实现多线程的第一种方式*      第一种方式:编写一个类,直接继承java.lang.Thread,重写run方法*/
public class ThreadDemo01 {public static void main(String[] args) {System.out.println("main start!");MyThread myThread = new MyThread();myThread.test();        // 不会启动线程// 只有调用s'tartmyThread.start();for (int i = 0; i < 10; i++) {System.out.println("main线程");}}
}
// 自定义线程类
class MyThread extends Thread{@Overridepublic void run(){Thread thread = Thread.currentThread();     // 获取当前线程thread.setName("自定义线程");    // 设置当前线程的名字String name = thread.getName();     // 获取当前线程的名字for (int i = 0; i < 10; i++) {System.out.println(name + i);}}public void test(){System.out.println("test");}
}

2.2 通过实现Runnable接口来创建并启动线程的步骤如下:

  1. 定义Runnable接口的实现类,并实现该接口的run()方法,该run()方法将作为线程执行体。
  2. 创建Runnable实现类的实例,并将其作为Threadtarget来创建Thread对象,Thread对象为线程对象。
  3. 调用线程对象的start()方法来启动该线程。
/*** 实现多线程的第二种方式*      第二种方式:编写一个类,实现java.lang.Runnable接口*/
public class ThreadDemo02 {public static void main(String[] args) {// 创建任务对象MyRunnable myRunnable = new MyRunnable();// 创建线程Thread tr = new Thread(myRunnable,"线程1");// 启动线程tr.start();System.out.println("主线程");// 除了上面使用的自定义类实现Runnable接口之外,还可以使用匿名内部类、lambda表达式来实现Runnable接口Runnable runnable1 = new Runnable() {@Overridepublic void run() {System.out.println("使用匿名内部类实现Runnable接口。。");}};new Thread(runnable1).start();Runnable runnable2 = ()->{String name = Thread.currentThread().getName();System.out.println(name + ":使用匿名内部类实现Runnable接口。。");};new Thread(runnable2).start();}
}
// 自定义类实现 Runnable 接口
class MyRunnable implements Runnable{@Overridepublic void run() {String name = Thread.currentThread().getName();System.out.println(name + "实现线程的第二种方式.");}
}

2.3 通过实现Callable接口来创建并启动线程的步骤如下:

  1. 创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,且该call()方法有返回值。然后再创建Callable实现类的实例。
  2. 使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值
  3. 使用FutureTask对象作为Thread对象的target创建并启动新线程。
  4. 调用FutureTask对象的get()方法来获得子线程执行结束后的返回值。
/*** 创建线程的第三种方式:*      实现Callable接口*/
public class ThreadDemo03 {public static void main(String[] args) throws ExecutionException, InterruptedException {// 使用匿名内部类实现Callable接口Callable<Integer> callable = new Callable<>() {@Overridepublic Integer call() throws Exception {int sum = 0;for (int i = 1; i < 10; i++) {sum += i;}// 返回一个结果return sum;}};// 创建一个FutureTask 对象,来接受异步计算的结果FutureTask<Integer> futureTask = new FutureTask<>(callable);// 创建线程Thread thread = new Thread(futureTask);thread.start();// futureTask.get() 是在等待执行完毕获取结果,所以是在线程启动之后,才获取。System.out.println(futureTask.get());}
}

采用继承Thread类的方式、实现Runnable、Callable接口的方式创建多线程的优缺点:

  • 线程类只是实现了Runnable接口或Callable接口,还可以继承其他类。而如果是已经继承Thread 类,则不能再继承其它父类了。(所以实现接口可以避免 java 中的单继承的局限性)
  • 在实现Runnable、Callable接口的这种方式下,多个线程可以共享同一个target对象,所以非常适合多个相同的程序代码的线程去共享同一个资源的情况,实现解耦操作,较好地体现了面向对象的思想。
  • 线程池只能放入实现 Runnable 或 Callable 类线程,不能直接放入继承 Thread 的类
  • 劣势是,编程稍稍复杂,如果需要访问当前线程,则必须使用Thread.currentThread()方法。
  • 采用继承Thread类的方式创建多线程的优势是,编写简单,如果需要访问当前线程,则无须使用Thread.currentThread()方法,直接使用this即可获得当前线程。
    鉴于上面分析,因此一般推荐采用实现Runnable接口、Callable接口的方式来创建多线程。

3 run()和start()有什么区别?

run()方法被称为线程执行体,它的方法体代表了线程需要完成的任务,而start()方法用来启动线程。调用start()方法启动线程时,系统会把该run()方法当成线程执行体来处理。但如果直接调用线程对象的run()方法,则run()方法立即就会被执行,而且在run()方法返回之前其他线程无法并发执行。也就是说,如果直接调用线程对象的run()方法,系统把线程对象当成一个普通对象,而run()方法也是一个普通方法,而不是线程执行体。

4 线程是否可以重复启动,会有什么后果?

只能对处于新建状态的线程调用start()方法,否则将引发IllegalThreadStateException异常。

扩展阅读

当程序使用new关键字创建了一个线程之后,该线程就处于新建状态,此时它和其他的Java对象一样,仅仅由Java虚拟机为其分配内存,并初始化其成员变量的值。此时的线程对象没有表现出任何线程的动态特征,程序也不会执行线程的线程执行体。

当线程对象调用了start()方法之后,该线程处于就绪状态,Java虚拟机会为其创建方法调用栈和程序计数器,处于这个状态中的线程并没有开始运行,只是表示该线程可以运行了。至于该线程何时开始运行,取决于JVM里线程调度器的调度。

5. 说一说sleep()和wait()的区别

  1. sleep()是Thread类中的静态方法,而wait()是Object类中的成员方法;
  2. sleep()可以在任何地方使用,而wait()只能在同步方法或同步代码块中使用;
  3. sleep()不会释放锁,而wait()会释放锁,并需要通过notify() / notifyAll()重新获取锁。

6. 说一说notify()、notifyAll()的区别

  • notify()

    用于唤醒一个正在等待相应对象锁的线程,使其进入就绪队列,以便在当前线程释放锁后竞争锁,进而得到CPU的执行。

  • notifyAll()

    用于唤醒所有正在等待相应对象锁的线程,使它们进入就绪队列,以便在当前线程释放锁后竞争锁,进而得到CPU的执行。

7. 如何实现子线程先执行,主线程再执行?

启动子线程后,立即调用该线程的join()方法,则主线程必须等待子线程执行完成后再执行。

扩展阅读

Thread类提供了让一个线程等待另一个线程完成的方法——join()方法。当在某个程序执行流中调用其他线程的join()方法时,调用线程将被阻塞,直到被join()方法加入的join线程执行完为止。

join()方法通常由使用线程的程序调用,以将大问题划分成许多小问题,每个小问题分配一个线程。当所有的小问题都得到处理后,再调用主线程来进一步操作。

8. Thread 类的方法

8.1 构造方法

Thread中常用的构造方法有:

  • public Thread() :分配一个新的线程对象。
  • public Thread(String name) :分配一个指定名字的新的线程对象。
  • public Thread(Runnable target) :分配一个带有指定目标新的线程对象。
  • public Thread(Runnable target,String name) :分配一个带有指定目标新的线程对象并指定名字

8.2 Thread 类的常用方法

  1. public static Thread currentThread() :返回对当前正在执行的线程对象的引用。

    Thread.currentThread(); // 执行这句代码的线程
    
  2. public void run(): 表示线程的任务。

    • 所有Thread的子类应该覆盖(重写)此方法
  3. public synchronized void start(): 线程开始执行;

    • 多次调用同一个线程的此方法是不合法的。
  4. public static native void sleep(long millis):使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行),具体取决于系统定时器和调度程序的精度和准确性。 线程不会丢失任何CPU的所有权。

    //线程休眠5S
    Thread.sleep(5000);	
    
  5. public static void sleep(long millis, int nanos) :使当前正在执行的线程以指定的毫秒数加上指定的纳秒数暂停(暂时停止执行)

  6. public final String getName():返回此线程的名称

    Thread.currentThread().getName();//获取当前线程名称
    
  7. public final synchronized void setName(String name):将此线程的名称更改为等于参数name

  8. public final int getPriority():返回此线程的优先级

  9. public final void setPriority(int newPriority):更改此线程的优先级,1~10之间

  10. public final native boolean isAlive():测试这个线程是否活着。 如果一个线程已经启动并且尚未死亡,那么线程是活着的

public static void main(String[] args) {Runnable runnable = new Runnable() {@Overridepublic void run() {for (int i = 0; i < 3; i++) {try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}};Thread thread = new Thread(runnable);// isAlive():测试这个线程是否活着System.out.println(thread.isAlive());       // falsethread.start();// 线程启动后尚未结束时返回 trueSystem.out.println(thread.isAlive());       // true
}
  1. public final void join():等待线程死亡,等同于join(0)
  2. public final synchronized void join(long millis):等待这个线程死亡的时间最多为millis毫秒。 0的超时意味着永远等待
    • join可以理解为当我们调用某个线程的这个方法时,这个方法会挂起调用线程,直到被调用线程结束执行,调用线程才会继续执行。(让父线程等待子线程结束之后才能继续运行)
 public static void main(String[] args){Thread th= new Thread(runnable);th.start();try {// 在main执行, main线程等待 th 执行完毕后再执行th.join();// main线程等待 th 执行 1s 后再执行
//            th.join(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("main end");}
  1. public void interrupt():中断这个线程,线程的中断状态标记为 true

  2. public static boolean interrupted():测试当前线程是否中断。 该方法可以清除线程的中断状态(设置中断状态为False) 。 换句话说,如果这个方法被连续调用两次,那么第二个调用将返回false(除非当前线程再次中断,在第一个调用已经清除其中断状态之后,在第二个调用之前已经检查过)。

  3. public boolean isInterrupted():测试这个线程是否被中断。 线程的中断状态不受此方法的影响。不清除中断状态。

public static void main(String[] args) {Runnable runnable = new Runnable() {@Overridepublic void run() {Thread thread = Thread.currentThread();for (int i = 0; i < 10; i++) {if (i % 3 == 0) {// 中断线程, 标记线程中断状态thread.interrupt();}// 测试当前线程是否中断System.out.println(Thread.interrupted());//true false false true false false true false false true}int count = 0;while (!thread.isInterrupted()) {if (count == 5) {// 当count == 5 时,线程就会被中断thread.interrupt(); // 我想停}System.out.println("执行" + count ++);    // 执行0 执行1 执行2 执行3 执行4 执行5}}};Thread thread = new Thread(runnable);thread.start();
}
    • public static native void yield():导致当前执行线程处于让步状态。如果有其他可运行线程具有至少与此线程同样高的优先级,那么这些线程接下来会被调度。并不一定会让出去。
  1. public State getState():返回此线程的状态,返回值是Thread的一个内部类,枚举类State。线程状态可以是:

    • NEW: 尚未启动的线程处于此状态。
    • RUNNABLE: 在Java虚拟机中执行的线程(可以运行的线程)处于此状态。
    • BLOCKED: 被阻塞等待监视器锁定的线程处于此状态。
    • WAITING: 正在等待另一个线程执行特定动作的线程处于此状态。
    • TIMED_WAITING: 正在等待另一个线程执行动作达到指定等待时间的线程处于此状态。 (sleep(1000),join(1000))
    • TERMINATED: 已退出的线程处于此状态。

相关文章:

关于Java多线程的那些事

多线程 多线程1. 关于多线程的理解1.1 进程和线程1.2 并行和并发1.3 线程调度 2. 创建多线程的方式创建线程有哪几种方式&#xff1f;2.1 通过继承Thread类来创建并启动线程的步骤如下&#xff1a;2.2 通过实现Runnable接口来创建并启动线程的步骤如下&#xff1a;2.3 通过实现…...

信息化项目验收的依据、内容和验收测评报告

随着信息系统业务覆盖率的提高和深度整合创新的逐步提高&#xff0c;信息系统运行阶段的复杂性和资源比例逐渐增加。一方面&#xff0c;信息已成为业务创新、技术应用和运营服务的综合体&#xff0c;而不仅仅是技术平台建设。另一方面&#xff0c;信息采购是技术平台建设。另一…...

解决IntelliJ IDEA执行maven打包,执行java -jar命令提示jar中没有主清单属性

问题场景 IDEA执行mvn clean package -DskipTesttrue命令或者借助工具的Maven菜单进行打包操作&#xff0c;然后执行java -jar app.jar命令后&#xff0c;提示jar中没有主清单属性 D:\WorkSpace\demo\target>java -jar demo-SNAPSHOT.jar demo-SNAPSHOT.jar中没有主清单属性…...

Python--文件和异常

目录 1、读取文件 1.1 读取文件的全部内容 1.2 相对路径和绝对路径 1.3 访问文件中的各行 1.4 使用文件中的内容 1.5 包含100万位的大型文件 1.6 圆周率中的生日 2、写入文件 2.1 写入一行 2.2 写入多行 3、异常 3.1 处理ZeroDivisionError 异常 3.2 使用try-exce…...

IDEFICS 简介: 最先进视觉语言模型的开源复现

我们很高兴发布 IDEFICS ( Image-aware Decoder Enhanced la Flamingo with Ininterleaved Cross-attention S ) 这一开放视觉语言模型。IDEFICS 基于 Flamingo&#xff0c;Flamingo 作为最先进的视觉语言模型&#xff0c;最初由 DeepMind 开发&#xff0c;但目前尚未公开发布…...

玩转Mysql系列 - 第20篇:异常捕获及处理详解

这是Mysql系列第20篇。 环境&#xff1a;mysql5.7.25&#xff0c;cmd命令中进行演示。 代码中被[]包含的表示可选&#xff0c;|符号分开的表示可选其一。 需求背景 我们在写存储过程的时候&#xff0c;可能会出现下列一些情况&#xff1a; 插入的数据违反唯一约束&#xff…...

一些工具类

1、字符串处理工具类 1.1、StrUtils package com.study.java8.util;/*** Classname&#xff1a;StrUtils* Description&#xff1a;字符串工具类* Date&#xff1a;2023/9/9 9:37* Author&#xff1a;jsz15*/import org.apache.commons.lang.text.StrBuilder; import org.apa…...

20230916后台面经整理

1.面对抢优惠券这样的高负载场景&#xff0c;你从架构、负载均衡等方面说一下你的设计&#xff1f; 答了参考Nginx进行负载均衡&#xff0c;然后在每台服务器怎么怎么弄&#xff08;架构每一层怎么设计&#xff09; 参考https://toutiao.io/posts/6z3uu2m/preview&#xff0c;h…...

如何通过快解析测试接口内外网?本地内网ip让外网访问连接

接口调试测试是网络技术员经常工作内容之一。如在公司内部api项目webserver测试&#xff0c;在公司内办公室个人电脑是正常用内网IP访问连接测试的&#xff0c;但在外网电脑需要远程测试时需要怎么测试呢&#xff1f;这里提供一种内网地址让外网访问的通用方法&#xff1a;快解…...

用c++实现五子棋小游戏

五子棋是一款经典小游戏&#xff0c;今天我们就用c实现简单的五子棋小游戏 目录 用到的算法&#xff1a; 思路分析 定义变量 开始写代码 完整代码 结果图&#xff1a; 用到的算法&#xff1a; 合法移动的判断&#xff1a;isValidMove 函数通过检查指定位置是否在棋盘范…...

Android 12.0 SystemUI下拉状态栏定制化之隐藏下拉通知栏布局功能实现(二)

1.前言 在12.0的系统定制化开发中,由于从12.0开始SystemUI下拉状态栏和11.0的变化比较大,所以可以说需要从新分析相关的SystemUI的 布局,然后做分析来实现不同的功能,今天就开始实现关于隐藏SystemUI下拉状态栏中的通知栏布局系列二,去掉下拉状态栏中 通知栏部分 白色的…...

通过finalshell快速在ubuntu上安装jdk1.8

这篇文章主要介绍一下怎么通过finalshell连接ubuntu&#xff0c;然后在ubuntu上安装jdk1.8&#xff0c;让不熟悉linux操作系统的童鞋也能快速地完成安装。 目录 一、准备一台虚拟机 二、安装finalshell远程连接工具 三、获取ubuntu虚拟机的ip地址 四、通过finalshell连接u…...

【Linux从入门到精通】多线程 | 线程互斥(互斥锁)

上篇文章我们对线程 | 线程介绍&线程控制介绍后&#xff0c;本篇文章将会对多线程中的线程互斥与互斥锁的概念进行详解。同时结合实际例子解释了可重入与不被重入函数、临界资源与临界区和原子性的概念。希望本篇文章会对你有所帮助。 文章目录 引入 一、重入与临界 1、1 可…...

Echarts 散点图的详细配置过程

文章目录 散点图 简介配置步骤简易示例 散点图 简介 Echarts散点图是一种常用的数据可视化图表类型&#xff0c;用于展示两个或多个维度的数据分布情况。散点图通过在坐标系中绘制数据点的位置来表示数据的关系。 Echarts散点图的特点如下&#xff1a; 二维数据展示&#xff…...

Nginx详解 五:反向代理

文章目录 1. 正向代理和反向代理1.1 正向代理概述1.1.1 什么是正向代理1.1.2 正向代理的作用1.1.3 正向代理的基本格式 1.2 反向代理概述1.2.1 什么是反向代理1.2.2 反向代理可实现的功能1.2.3 反向代理的可用模块 2. 配置反向代理2.1 反向代理配置参数2.1.1 proxy_pass2.1.2 其…...

【PDF密码】PDF文件打开之后不能打印,怎么解决?

正常的PDF文件是可以打印的&#xff0c;如果PDF文件打开之后发现文件不能打印&#xff0c;我们需要先查看一下自己的打印机是否能够正常运行&#xff0c;如果打印机是正常的&#xff0c;我们再查看一下&#xff0c;文件中的打印功能按钮是否是灰色的状态。 如果PDF中的大多数功…...

深入解析 qsort 函数(下),用冒泡排序模拟实现 qsort 函数

前言&#xff1a;对于库函数有适当了解的朋友们&#xff0c;对于 qsort 函数想必是有认知的&#xff0c;因为他可以对任意数据类型进行排序的功能属实是有点厉害的&#xff0c;本次分享&#xff0c;笔者就给大家带来 qsort 函数的全面的解读 本次知识的分享笔者分为上下俩卷文章…...

Azure + React + ASP.NET Core 项目笔记一:项目环境搭建(二)

有意义的标题 pnpm 安装umi4 脚手架搭建打包语句变更Visual Studio调试Azure 设置变更发布 pnpm 安装 参考官网&#xff0c;或者直接使用npm安装 npm install -g pnpmumi4 脚手架搭建 我这里用的umi4&#xff0c;官网已附上 这里需要把clientapp清空&#xff0c;之后 cd Cl…...

Vmware通过VMware tools设置共享文件夹

步骤说明&#xff1a; 先安装VMware tools&#xff0c;再设置共享文件夹即可。 写在前面&#xff1a; 刚安装虚拟机时&#xff0c;窗口可能显得太小&#xff0c;这是窗口分辨率没有调整导致的。 点击设置->显示->分辨率调整即可 一、安装VMware tools 1.1 点击虚拟机…...

RPA机器人流程自动化专题培训大纲 (针对大学生的版本)

一、课程简介 RPA机器人流程自动化是一种新兴的技术&#xff0c;它通过软件机器人模拟人类操作计算机完成重复性任务&#xff0c;从而实现业务流程的自动化。本课程旨在介绍RPA机器人流程自动化的基本概念、原理和应用&#xff0c;并通过实践案例演示如何应用RPA机器人流程自动…...

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …...

TDengine 快速体验(Docker 镜像方式)

简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能&#xff0c;本节首先介绍如何通过 Docker 快速体验 TDengine&#xff0c;然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker&#xff0c;请使用 安装包的方式快…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

css实现圆环展示百分比,根据值动态展示所占比例

代码如下 <view class""><view class"circle-chart"><view v-if"!!num" class"pie-item" :style"{background: conic-gradient(var(--one-color) 0%,#E9E6F1 ${num}%),}"></view><view v-else …...

.Net框架,除了EF还有很多很多......

文章目录 1. 引言2. Dapper2.1 概述与设计原理2.2 核心功能与代码示例基本查询多映射查询存储过程调用 2.3 性能优化原理2.4 适用场景 3. NHibernate3.1 概述与架构设计3.2 映射配置示例Fluent映射XML映射 3.3 查询示例HQL查询Criteria APILINQ提供程序 3.4 高级特性3.5 适用场…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络&#xff0c;将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具&#xff0c;支持 Chrome、Firefox、Safari 等主流浏览器&#xff0c;提供多语言 API&#xff08;Python、JavaScript、Java、.NET&#xff09;。它的特点包括&a…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

2025盘古石杯决赛【手机取证】

前言 第三届盘古石杯国际电子数据取证大赛决赛 最后一题没有解出来&#xff0c;实在找不到&#xff0c;希望有大佬教一下我。 还有就会议时间&#xff0c;我感觉不是图片时间&#xff0c;因为在电脑看到是其他时间用老会议系统开的会。 手机取证 1、分析鸿蒙手机检材&#x…...

自然语言处理——循环神经网络

自然语言处理——循环神经网络 循环神经网络应用到基于机器学习的自然语言处理任务序列到类别同步的序列到序列模式异步的序列到序列模式 参数学习和长程依赖问题基于门控的循环神经网络门控循环单元&#xff08;GRU&#xff09;长短期记忆神经网络&#xff08;LSTM&#xff09…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...