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

java 并发

目录

  • 什么是线程?什么是进程?为什么要有线程?有什么关系与区别?
  • 什么是守护线程?
  • 如何创建、启动 Java 线程?
  • 线程池参数
  • 详细解释Callable接口和Future类
  • 偏向锁 / 轻量级锁 / 重量级锁
  • synchronized 和 java.util.concurrent.lock.Lock 之间的区别
  • synchronized 和 java.util.concurrent.lock.Lock 之间的区别
  • java.util.concurrent.lock.Lock 与 java.util.concurrent.lock.ReadWriteLock 之间的区别
  • 什么是死锁?发生的条件,避免死锁
  • 介绍一下ForkJoinPool的使用

什么是线程?什么是进程?为什么要有线程?有什么关系与区别?

线程:
线程是进程中的最小执行单元,是CPU调度的基本单位。一个进程可以包含多个线程,这些线程共享进程的资源,包括内存空间、文件描述符等。线程之间可以并发执行,使得程序可以同时处理多个任务,提高了系统的响应能力和并发性。

进程:
进程是操作系统中的一个执行实例,是程序在计算机上的一次执行活动。每个进程都有自己独立的内存空间和系统资源,进程之间是相互独立的。进程的切换代价相对较高,因为需要保存和恢复进程的所有状态信息。

为什么要有线程?
在单核CPU时代,进程是独立运行的,每个进程有自己的地址空间,进程之间切换开销大。为了充分利用CPU的计算资源,提高系统并发能力,引入了线程的概念。线程在同一个进程内共享进程的资源,线程间切换开销较小,可以实现更高效的多任务处理。

关系与区别:

  • 关系:线程是进程的一部分,一个进程可以包含多个线程。线程共享进程的资源,包括内存空间、文件描述符等。
  • 区别:进程是一个独立的执行实例,有自己独立的内存空间和系统资源。线程是进程的最小执行单元,多个线程共享进程的资源。进程之间相互独立,线程之间可以并发执行,共享进程的资源。

总结:线程是进程内部的执行流,是处理器执行任务的最小单位。一个进程可以包含多个线程,线程之间可以并发执行,共享进程的资源,从而提高系统的并发性和性能。多线程编程可以实现更高效的多任务处理,但也需要注意线程同步和共享资源的安全性问题。

什么是守护线程?

守护线程(Daemon Thread)是一种特殊类型的线程,其特点是在程序运行时在后台提供一种通用服务的功能。与普通线程(用户线程)相对应,守护线程的生命周期依赖于程序中是否还存在正在运行的用户线程。当所有的用户线程结束运行时,守护线程会被自动终止,而不会等待其运行完成。

在Java中,通过调用Thread类的setDaemon(true)方法将线程设置为守护线程。守护线程通常用于提供程序的支持和后台服务,如垃圾回收器(GC线程)就是一个典型的守护线程。垃圾回收器在程序运行过程中自动回收不再使用的对象,但当所有用户线程执行完毕时,程序就终止了,此时也不需要再继续执行垃圾回收的工作,因此垃圾回收线程会自动终止。

守护线程的一个重要应用场景是Web服务器,它可以创建一个守护线程来处理网络连接,如果所有的用户请求线程都结束了,服务器就没有处理请求的必要了,守护线程会自动退出。

需要注意的是,守护线程并不适合处理需要完整执行的任务,因为它的生命周期是不可控的,当所有用户线程结束时,它会被强制终止,可能导致任务未完成。因此,守护线程适合处理后台服务和支持性工作,而不适合处理关键业务逻辑。

如何创建、启动 Java 线程?

在Java中,创建和启动线程通常有两种方式:继承Thread类和实现Runnable接口。

1. 继承Thread类:
创建一个继承自Thread类的子类,并重写run()方法来定义线程的执行逻辑。然后通过调用start()方法来启动线程。示例代码如下:

public class MyThread extends Thread {@Overridepublic void run() {// 线程执行逻辑System.out.println("Thread is running!");}public static void main(String[] args) {MyThread thread = new MyThread();thread.start(); // 启动线程}
}

2. 实现Runnable接口:
创建一个实现了Runnable接口的类,并实现run()方法来定义线程的执行逻辑。然后将实现了Runnable接口的类作为参数传递给Thread类的构造方法,并调用start()方法启动线程。示例代码如下:

public class MyRunnable implements Runnable {@Overridepublic void run() {// 线程执行逻辑System.out.println("Thread is running!");}public static void main(String[] args) {MyRunnable myRunnable = new MyRunnable();Thread thread = new Thread(myRunnable);thread.start(); // 启动线程}
}

无论是继承Thread类还是实现Runnable接口,调用start()方法后,线程会进入就绪状态,并由Java虚拟机自动调度执行。需要注意的是,线程的执行顺序是由系统的线程调度器决定的,因此线程的执行顺序可能是随机的。

除了继承Thread类和实现Runnable接口外,还可以使用Callable接口和Future类创建线程。Callable接口允许线程返回一个结果,而Future类可以用于获取Callable线程的返回值。这是一种更加灵活的方式来创建和管理线程。

线程池参数

在Java中,线程池的参数主要由ThreadPoolExecutor类的构造方法来定义,它的构造方法有以下几个参数:

  1. corePoolSize:
    表示线程池的核心线程数,也就是线程池中始终保持活动状态的线程数量。即使这些线程处于空闲状态,也不会被回收。当有新的任务提交时,如果核心线程数还没有达到上限,会优先创建新的核心线程来执行任务。

  2. maximumPoolSize:
    表示线程池的最大线程数,包括核心线程和非核心线程。当有新的任务提交时,如果核心线程数已满,并且线程池中的线程数量还没有达到最大线程数,会创建新的非核心线程来执行任务。当线程池中的线程数达到最大线程数后,如果任务继续提交,任务会被放入任务队列中等待执行。

  3. keepAliveTime:
    表示非核心线程的空闲时间。当非核心线程空闲时间超过该值时,会被回收释放,以减少线程池的线程数量。这个参数只有在allowCoreThreadTimeOut设置为true时才生效。

  4. unit:
    表示keepAliveTime的时间单位,可以是TimeUnit.SECONDSTimeUnit.MINUTES等等。

  5. workQueue:
    表示任务队列,用于存放等待执行的任务。当线程池的线程数达到核心线程数后,后续提交的任务会被放入任务队列中等待执行。线程池提供了多种任务队列的实现,常用的有ArrayBlockingQueueLinkedBlockingQueueSynchronousQueue等。

  6. threadFactory:
    表示线程工厂,用于创建新的线程。可以通过自定义线程工厂来给线程设置特定的名称、优先级等。

  7. handler:
    表示线程池的拒绝策略,当线程池的任务队列和线程数都已满,无法继续接收新的任务时,会根据指定的拒绝策略来处理这些任务。常用的拒绝策略有ThreadPoolExecutor.AbortPolicy(抛出异常)、ThreadPoolExecutor.CallerRunsPolicy(由提交任务的线程来执行任务)、ThreadPoolExecutor.DiscardPolicy(直接丢弃任务)等。

综上所述,线程池的参数主要包括核心线程数、最大线程数、非核心线程的空闲时间、任务队列、线程工厂和拒绝策略等。合理地设置这些参数可以根据系统的需求来控制线程池的并发度、资源消耗和任务调度,以达到最优的性能和资源利用率。

详细解释Callable接口和Future类

Callable接口和Future类是Java多线程中用于处理有返回值的任务的一组接口和类。它们通常与线程池结合使用,使得多线程编程更加灵活和高效。

Callable接口:
Callable接口是一个泛型接口,定义了一个带有返回值的任务,它只有一个方法call(),没有像Runnable接口那样的run()方法。call()方法可以返回一个结果,并且可以抛出异常。通常情况下,我们可以通过实现Callable接口来创建具有返回值的任务,并将任务提交给线程池执行。Callable接口的定义如下:

public interface Callable<V> {V call() throws Exception;
}

Future类:
Future类是一个接口,它代表了异步计算的结果。当一个线程提交了一个Callable任务到线程池后,线程池会返回一个Future对象,通过该对象可以获得任务的执行结果。Future接口定义了一些方法,用于查询任务是否完成、获取任务的执行结果或者取消任务的执行。常用的Future实现类是FutureTaskFuture接口的定义如下:

public interface Future<V> {boolean cancel(boolean mayInterruptIfRunning);boolean isCancelled();boolean isDone();V get() throws InterruptedException, ExecutionException;V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
}

通过Future对象,我们可以在主线程中继续执行其他任务,然后在需要获取任务结果的地方调用get()方法来等待任务执行完成并获取结果。如果任务还没有执行完成,get()方法将会阻塞主线程,直到任务执行完成并返回结果。如果不想等待任务执行完成,可以使用isDone()方法来判断任务是否完成。

总结:Callable接口用于定义带有返回值的任务,Future类用于获取任务的执行结果或者取消任务的执行。通过这两个接口,我们可以更好地管理多线程任务,实现高效的并发编程。

偏向锁 / 轻量级锁 / 重量级锁

偏向锁、轻量级锁、重量级锁都是Java中用于优化锁的实现,针对不同的锁竞争场景,采用不同的策略来提高锁的性能。

1. 偏向锁(Biased Locking):
偏向锁是Java中针对单线程访问同步块的优化措施。它的设计思想是假设在大多数情况下,锁只会被一个线程访问,因此当一个线程访问同步块时,会将对象头中的标记设置为偏向锁,并记录下持有偏向锁的线程ID。这样,下次这个线程再次访问同步块时,就无需再进行加锁操作,而是直接进入临界区。如果有其他线程尝试竞争偏向锁,偏向锁就会升级为轻量级锁。

2. 轻量级锁(Lightweight Locking):
轻量级锁是针对多个线程交替执行同步块的优化措施。当一个线程尝试获取锁时,会先在栈帧中分配一块用于存储锁记录的空间,并将对象头中的标记设置为轻量级锁。然后线程尝试使用CAS(比较并交换)操作来尝试获取锁,如果获取成功,则进入临界区执行。如果CAS操作失败,说明有其他线程也在竞争锁,这时轻量级锁会膨胀为重量级锁。

3. 重量级锁(Heavyweight Locking):
重量级锁是Java中默认的锁实现,用于处理复杂的锁竞争场景。当一个线程尝试获取锁时,会进入重量级锁的阻塞状态,操作系统会将该线程挂起,直到锁被释放,然后唤醒该线程。重量级锁采用操作系统的原生锁机制,会涉及用户态和内核态的切换,开销较大,适用于竞争激烈的情况。

在锁的优化中,JVM会根据线程竞争的情况自动选择偏向锁、轻量级锁或重量级锁来提高锁的性能。偏向锁适用于只有一个线程访问同步块的情况,轻量级锁适用于多个线程交替执行同步块的情况,而重量级锁适用于竞争激烈的情况。这些优化措施都是为了减少锁的开销,提高程序的并发性能。

synchronized 和 java.util.concurrent.lock.Lock 之间的区别

synchronizedjava.util.concurrent.lock.Lock都是Java中用于实现线程同步的机制,但它们之间有一些重要的区别:

  1. 锁的类型:

    • synchronized是Java中的关键字,属于内置锁(Intrinsic Lock),可以直接在方法或代码块中使用。每个Java对象都有一个内置锁,通过synchronized关键字来获取。
    • java.util.concurrent.lock.Lock是Java并发包中提供的接口,属于显式锁(Explicit Lock)。它提供了更灵活的锁定和释放机制,并且可以有多个条件变量。
  2. 获取锁的方式:

    • synchronized的获取锁是隐式的,在进入synchronized代码块或方法时自动获取锁,在退出代码块或方法时自动释放锁。
    • java.util.concurrent.lock.Lock的获取锁是显式的,需要手动调用lock()方法来获取锁,调用unlock()方法来释放锁。这样可以更精确地控制锁的范围和持有时间。
  3. 锁的可中断性:

    • synchronized获取锁的过程是不可中断的,即使其他线程尝试中断持有锁的线程,也无法中断。
    • java.util.concurrent.lock.Lock中的锁可以通过lockInterruptibly()方法实现可中断的获取锁操作,当其他线程中断当前线程时,可以中断获取锁的过程。
  4. 锁的公平性:

    • synchronized锁是非公平的,当一个线程释放锁后,任何一个等待该锁的线程都有机会获取锁。
    • java.util.concurrent.lock.Lock中的锁可以是公平的,通过ReentrantLock类的构造函数可以指定是否使用公平锁,默认是非公平锁。
  5. 灵活性和功能:

    • java.util.concurrent.lock.Lock提供了更多的功能,例如可以尝试获取锁、设定获取锁的超时时间、创建多个条件变量等,可以满足更复杂的同步需求。
    • synchronized相对简单,适用于一些简单的同步需求,而且在JVM中使用synchronized的优化措施,如偏向锁、轻量级锁等,可以带来一定的性能优势。

总体而言,对于简单的同步需求,synchronized是较为方便的选择。而对于复杂的同步需求,或者需要更精细地控制锁的行为,java.util.concurrent.lock.Lock提供了更多的灵活性和功能,可以更好地满足需求。

synchronized 和 java.util.concurrent.lock.Lock 之间的区别

synchronizedjava.util.concurrent.lock.Lock都是Java中用于实现线程同步的机制,但它们之间有一些重要的区别:

  1. 锁的类型:

    • synchronized是Java中的关键字,属于内置锁(Intrinsic Lock),可以直接在方法或代码块中使用。每个Java对象都有一个内置锁,通过synchronized关键字来获取。
    • java.util.concurrent.lock.Lock是Java并发包中提供的接口,属于显式锁(Explicit Lock)。它提供了更灵活的锁定和释放机制,并且可以有多个条件变量。
  2. 获取锁的方式:

    • synchronized的获取锁是隐式的,在进入synchronized代码块或方法时自动获取锁,在退出代码块或方法时自动释放锁。
    • java.util.concurrent.lock.Lock的获取锁是显式的,需要手动调用lock()方法来获取锁,调用unlock()方法来释放锁。这样可以更精确地控制锁的范围和持有时间。
  3. 锁的可中断性:

    • synchronized获取锁的过程是不可中断的,即使其他线程尝试中断持有锁的线程,也无法中断。
    • java.util.concurrent.lock.Lock中的锁可以通过lockInterruptibly()方法实现可中断的获取锁操作,当其他线程中断当前线程时,可以中断获取锁的过程。
  4. 锁的公平性:

    • synchronized锁是非公平的,当一个线程释放锁后,任何一个等待该锁的线程都有机会获取锁。
    • java.util.concurrent.lock.Lock中的锁可以是公平的,通过ReentrantLock类的构造函数可以指定是否使用公平锁,默认是非公平锁。
  5. 灵活性和功能:

    • java.util.concurrent.lock.Lock提供了更多的功能,例如可以尝试获取锁、设定获取锁的超时时间、创建多个条件变量等,可以满足更复杂的同步需求。
    • synchronized相对简单,适用于一些简单的同步需求,而且在JVM中使用synchronized的优化措施,如偏向锁、轻量级锁等,可以带来一定的性能优势。

总体而言,对于简单的同步需求,synchronized是较为方便的选择。而对于复杂的同步需求,或者需要更精细地控制锁的行为,java.util.concurrent.lock.Lock提供了更多的灵活性和功能,可以更好地满足需求。

java.util.concurrent.lock.Lock 与 java.util.concurrent.lock.ReadWriteLock 之间的区别

java.util.concurrent.lock.Lockjava.util.concurrent.lock.ReadWriteLock都是Java并发包中用于实现线程同步的接口,它们之间的区别主要在于锁的类型和用途:

1. 锁的类型:

  • java.util.concurrent.lock.Lock是一种通用的锁接口,用于实现基本的互斥锁。它提供了两个基本方法:lock()用于获取锁,unlock()用于释放锁。Lock接口的实现类ReentrantLock是一种可重入锁,它允许同一个线程多次获取同一个锁,避免了死锁的问题。

  • java.util.concurrent.lock.ReadWriteLock是一种读写锁接口,它可以让多个线程同时读取共享资源,但在写操作时需要互斥。ReadWriteLock接口提供了两个锁:读锁(读共享锁)和写锁(写独占锁)。读锁可以被多个线程同时获取,用于读取共享资源;而写锁只能被一个线程获取,用于修改共享资源。

2. 用途:

  • java.util.concurrent.lock.Lock适用于一般性的互斥场景,它提供了灵活的锁定和解锁机制,可以手动控制锁的获取和释放。它的实现类ReentrantLock可以实现公平锁或非公平锁,也支持可中断的获取锁操作。

  • java.util.concurrent.lock.ReadWriteLock适用于读多写少的场景,它可以提高读操作的并发性能。在读多写少的情况下,多个线程可以同时获取读锁来读取共享资源,而只有在写操作时需要排他性,此时才需要获取写锁。

综上所述,Lock接口适用于通用的互斥场景,提供了灵活的锁定和解锁机制;而ReadWriteLock接口适用于读多写少的场景,可以提高读操作的并发性能。在不同的场景下,可以根据需求选择合适的锁实现。

什么是死锁?发生的条件,避免死锁

死锁发生的条件

互斥,共享资源只能被一个线程占用
占有且等待,线程 t1 已经取得共享资源 s1,尝试获取共享资源 s2 的时候,不释放共享资源 s1
不可抢占,其他线程不能强行抢占线程 t1 占有的资源 s1
循环等待,线程 t1 等待线程 t2 占有的资源,线程 t2 等待线程 t1 占有的资源

避免死锁的方法

对于以上 4 个条件,只要破坏其中一个条件,就可以避免死锁的发生。

对于第一个条件 “互斥” 是不能破坏的,因为加锁就是为了保证互斥。

其他三个条件,我们可以尝试

一次性申请所有的资源,破坏 “占有且等待” 条件
占有部分资源的线程进一步申请其他资源时,如果申请不到,主动释放它占有的资源,破坏 “不可抢占” 条件
按序申请资源,破坏 “循环等待” 条件

介绍一下ForkJoinPool的使用

相关文章:

java 并发

目录 什么是线程&#xff1f;什么是进程&#xff1f;为什么要有线程&#xff1f;有什么关系与区别&#xff1f;什么是守护线程&#xff1f;如何创建、启动 Java 线程&#xff1f;线程池参数详细解释Callable接口和Future类偏向锁 / 轻量级锁 / 重量级锁synchronized 和 java.ut…...

【MySQL】DDL和DML

4&#xff0c;DDL:操作数据库 我们先来学习DDL来操作数据库。而操作数据库主要就是对数据库的增删查操作。 4.1 查询 查询所有的数据库 SHOW DATABASES; 运行上面语句效果如下&#xff1a; 上述查询到的是的这些数据库是mysql安装好自带的数据库&#xff0c;我们以后不要操…...

使用python框架FastAPI

中文文档 Python ORM之SQLAlchemy Fastapi大型项目目录规划 SQL数据库操作 依赖项Depends 待看 和APIRouter from sqlalchemy import create_engine from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmakerapp FastAPI()SQ…...

Vue实现leafletMap自定义绘制线段 并且删除指定的已绘制的点位

效果&#xff1a;点击表格可实现选中地图点位&#xff0c;删除按钮点击可删除对应点位并且重新绘制线段&#xff0c;点击确定按钮 保存已经绘制的点位信息传给父组件 并且该组件已实现回显 完整的组件代码如下 文件名称为&#xff1a; leafletMakePointYt <!--* Descripti…...

ChatGPT辅助写论文:提升效率与创造力的利器

写作是人类最重要的交流方式之一&#xff0c;也是学术研究中不可或缺的环节。然而&#xff0c;写作并不是一件容易的事情&#xff0c;尤其是对于科研人员来说&#xff0c;他们需要花费大量的时间和精力来撰写高质量的论文&#xff0c;并且面临着各种各样的挑战&#xff0c;如语…...

面试攻略,Java 基础面试 100 问(六)

JAVA 泛型 泛型提供了编译时类型安全检测机制&#xff0c;该机制允许程序员在编译时检测到非法的类型。泛型的本 质是参数化类型&#xff0c;也就是说所操作的数据类型被指定为一个参数。比如我们要写一个排序方法&#xff0c; 能够对整型数组、字符串数组甚至其他任何类型的…...

图解系列 DNS查找过程和DNS缓存

DNS 充当地址簿。它将人类可读的域名 (google.com) 转换为机器可读的 IP 地址 (142.251.46.238)。 开局一张图 来自&#xff1a;https://xiaolishen.medium.com/the-dns-lookup-journey-240e9a5d345c 寻址流程 查询浏览器缓存&#xff1a;当你输入一个域名后&#xff0c;浏览…...

《吐血整理》高级系列教程-吃透Fiddler抓包教程(21)-如何使用Fiddler生成Jmeter脚本-上篇

1.简介 我们知道Jmeter本身可以录制脚本&#xff0c;也可以通过BadBoy&#xff0c;BlazeMeter等工具进行录制&#xff0c;其实Fiddler也可以录制Jmter脚本&#xff08;而且有些页面&#xff0c;由于安全设置等原因&#xff0c;使用Jmeter直接无法打开录制时&#xff0c;这时就…...

vim中出现复制不对齐-乱码问题

不对齐解决&#xff1a; 使用纯文本模式粘贴&#xff1a;在进入 Vim 编辑器后&#xff0c;先按下 :set paste 进入插入模式&#xff0c;然后再进行粘贴操作。这样可以确保粘贴的文本以纯文本格式插入&#xff0c;而不会触发自动缩进或其他格式化操作 中文乱码问题&#xff1a;…...

华为OD机考真题--单词接龙--带答案

2023华为OD统一考试&#xff08;AB卷&#xff09;题库清单-带答案&#xff08;持续更新&#xff09;or2023年华为OD真题机考题库大全-带答案&#xff08;持续更新&#xff09; 题目描述&#xff1a; 单词接龙的规则是&#xff1a; 用于接龙的单词首字母必须要前一个单词的尾字母…...

排序进行曲-v3.0

文章目录 小程一言归并排序步骤举例总结时间复杂度分析&#xff1a;空间复杂度分析&#xff1a;注意 应用场景总结 实际举例Other 代码实现结果解释 小程一言 这篇文章是在排序进行曲2.0之后的续讲&#xff0c; 这篇文章主要是对归并排序进行细致分析&#xff0c;以及操作。 希…...

编辑列表操作时的一些思考,关于全量和增量操作

假设我有一个这样的页面&#xff0c;需要对用户的信息做编辑操作 角色下面有一些菜单项&#xff0c;通过一张角色-菜单关系表来维护&#xff0c;那么我要在编辑用户后也要对用户角色关系表做修改&#xff0c;是经过两次比较分别计算出需要增加或者删除的角色用户关系&#xff0…...

【python】Python tkinter库实现重量单位转换器的GUI程序

文章目录 前言学到什么?导入模块和库创建一个GUI窗口定义函数 from_kg()创建标签、输入框、文本框和按钮设置组件的布局运行窗口循环完整代码运行效果结束语 前言 这段代码是一个简单的重量单位转换器的 GUI 程序&#xff0c;使用了 Python 的 tkinter 库来创建图形界面。该程…...

CVPR2023新作:源数据集对迁移学习性能的影响以及相应的解决方案

Title: A Data-Based Perspective on Transfer Learning (迁移学习的基于数据的观点) Affiliation: MIT (麻省理工学院) Authors: Saachi Jain, Hadi Salman, Alaa Khaddaj, Eric Wong, Sung Min Park, Aleksander Mądry Keywords: transfer learning, source dataset, dow…...

《TCP IP 网络编程》第十五章

第 15 章 套接字和标准I/O 15.1 标准 I/O 的优点 标准 I/O 函数的两个优点&#xff1a; 除了使用 read 和 write 函数收发数据外&#xff0c;还能使用标准 I/O 函数收发数据。下面是标准 I/O 函数的两个优点&#xff1a; 标准 I/O 函数具有良好的移植性标准 I/O 函数可以利用…...

新特性解读 | MySQL 8.0 字段信息统计机制

作者通过一个案例详细说明了 MySQL 8.0 字段信息统计机制的相关参数和使用方式。 作者&#xff1a;杨奇龙 网名“北在南方”&#xff0c;资深 DBA&#xff0c;主要负责数据库架构设计和运维平台开发工作&#xff0c;擅长数据库性能调优、故障诊断。 本文来源&#xff1a;原创投…...

基于Java+Swing实现超级玛丽游戏

基于JavaSwing实现超级玛丽游戏 一、系统介绍二、功能展示三、其他系统 一、系统介绍 超级玛丽小游戏的JAVA程序&#xff0c;进入游戏后首先按空格键开始&#xff0c;利用方向键来控制的马里奥的移动&#xff0c;同时检测马里奥与场景中的障碍物和敌人的碰撞&#xff0c;并判断…...

Day12-1-Webpack前端工程化开发

Webpack前端工程化 1 案例-webpack打包js文件 1 在index.html中编写代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><me…...

JUnit教程_编程入门自学教程_菜鸟教程-免费教程分享

教程简介 JUnit是一个Java语言的单元测试框架。它由Kent Beck和Erich Gamma建立&#xff0c;逐渐成为源于Kent Beck的sUnit的xUnit家族中最为成功的一个。 JUnit有它自己的JUnit扩展生态圈。多数Java的开发环境都已经集成了JUnit作为单元测试的工具。JUnit是由 Erich Gamma 和…...

Hive 安装介绍

介绍 Hive是基于Hadoop的一个数据仓库工具&#xff0c;可以将结构化的数据文件映射为一张数据库表&#xff0c;并提供类SQL查询功能。 其本质是将SQL转换为MapReduce的任务进行运算&#xff0c;底层由HDFS来提供数据的存储&#xff0c;说白了hive可以理解为一个将SQL转换为Ma…...

npm ERR! code EPERM npm ERR! syscall unlink npm ERR!错误解决方法

npm ERR! code EPERM npm ERR! syscall unlink npm ERR!错误解决方法 1、问题描述2、解决方法 1、问题描述 由于之前电脑系统的原因&#xff0c;电脑重置了一下&#xff0c;之前安装的环境都没了&#xff0c;然后在重新安装node.js后在使用npm安装时总是报如下错误&#xff1a…...

redis 高级篇4 分布式锁

一 redis架构图 1.1 redis的架构图 1.2 分布式锁满足条件 1.独占性&#xff1b;2.高可用&#xff1b;3.防死锁&#xff1b;4.不乱抢&#xff1b;5.重入性 二 分布式锁的案例情况 2.1 分布式锁1:单机分布式部署 描述&#xff1a; 使用lock锁和synchronized&#xff0c;单机…...

TPU-NNTC 编译部署LPRNet 车牌识别算法

TPU-NNTC 编译部署LPRNet 车牌识别算法 注意&#xff1a; 由于SOPHGO SE5微服务器的CPU是基于ARM架构&#xff0c;以下步骤将在基于x86架构CPU的开发环境中完成 初始化开发环境(基于x86架构CPU的开发环境中完成)模型转换 (基于x86架构CPU的开发环境中完成) 处理后的LPRNet 项…...

在线/开源GNSS处理软件/平台介绍

当前&#xff0c;存在较多的GNSS开源/免费软件&#xff0c;可用于质量检核、RTK解算和PPP解算等&#xff0c;本文总结了部分常用的处理软件&#xff0c;其详细信息如表1和表2所示。 表1 常用GNSS预处理&#xff08;格式转换、质量检核&#xff09;软件&#xff1a; 软件名称 …...

SpringBoot集成企业微信群聊机器人消息

目录 参考文档概述一、功能作用二、应用场景三、 群机器人发送限制四、创建机器人1、添加2、群机器人Webhook地址 五、发送消息1、文本 text请求体 图文连接 news 参考文档 官方文档 企业微信群机器人应用 概述 现在很多企业都在使用企业微信进行工作交流&#xff0c;自从企…...

​五、驱动 - ​音频系统硬件电路

文章目录 1. 音频系统硬件电路结构2. 蓝牙音频2.1 音乐播放2.2 VoIP通话2.3 4G通话3. 其他3.1 什么是S/PDIF1. 音频系统硬件电路结构 录音放音设备:mic、speaker、耳机、听筒这些带有录音放音功能的设备(因为录放设备可能是模拟设备也可能是数字设备,所以接口可能是模拟接口…...

【图像分割和识别】活动形状模型 (ASM) 和活动外观模型 (AAM)(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…...

HTML基础介绍2

表单格式化 ctrld&#xff1a;复制选中行数的所有代码 ctrlx&#xff1a;删除代码 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>表单综合案例</title> </head> <body> <!--…...

rar压缩包怎么改成zip格式

不知道大家有没有遇到需要转换压缩包格式的问题&#xff0c;今天想和大家分享rar压缩包改成zip格式的方法。 方法一&#xff1a; 直接修改rar压缩包的后缀名变为zip&#xff0c;就可以修改压缩包文件格式了 方法二&#xff1a; 先将rar压缩包解压出来&#xff0c;然后再将解…...

Mac 补丁管理

Mac 补丁管理涉及通过扫描收集所有缺失补丁的完整列表、下载缺失的补丁、在非生产计算机上测试它们&#xff0c;最后将它们推广到生产环境中进行部署来管理 macOS 端点&#xff0c;修补 Mac 设备&#xff08;又称 Mac 修补&#xff09;可增强 macOS 环境的安全级别。 什么是 m…...