福州网站制作套餐/东莞seo计费管理
目录
- 异步回调
- JMM 理解
- 对 volatile 的理解
- 1、保证可见性
- 2、不保证原子性
- 3、禁止指令重排
- 对 JMM 的理解
- 详解单例模式
- 饿汉式
- 懒汉式
- DCL懒汉式:双重检测锁模式的懒汉式单例
- 静态内部类实现单例
- 通过反射破坏单例,修改后的DCL饿汉式
- 枚举实现单例防止反射破坏
- 理解 CAS(compareAndSwap)
- CAS 出现的 ABA 问题
- 理解 ABA 问题
- 解决 ABA 问题(带版本号的原子操作、乐观锁思想)
- 公平锁,非公平锁
- 可重入锁(递归锁)
- 自旋锁
- 排除死锁
异步回调
Future 设计的初衷: 对将来的某个事件的结果进行建模
- 没有返回值的 runAsync 异步回调
import java.util.concurrent.*;/*** 异步调用: CompletableFuture* 异步执行* 成功回调* 失败回调*/
public class test {public static void main(String[] args) throws ExecutionException, InterruptedException {//发起一个请求 void// 没有返回值的 runAsync 异步回调CompletableFuture<Void> completableFuture = CompletableFuture.runAsync(() -> {try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "runAsync=>void");});System.out.println("11111111");completableFuture.get();//获取执行结果}
}
- 有返回值的异步回调 supplyAsync
import java.util.concurrent.*;/*** 异步调用: CompletableFuture* 异步执行* 成功回调* 失败回调*/
public class test {public static void main(String[] args) throws ExecutionException, InterruptedException {// completableFuture.get(); // 获取阻塞执行结果// 有返回值的 supplyAsync 异步回调// ajax,成功和失败的回调// 失败返回的是错误信息;CompletableFuture<Integer> completableFuture = CompletableFuture.supplyAsync(() -> {System.out.println(Thread.currentThread().getName() + "supplyAsync=>Integer");//int i = 10 / 0;return 1024;});//whenComplete: 参数BiConsumer<T, U>// 有两个参数,一个是T 一个是U,T:是代表的 正常返回的结果;U:是代表的 抛出异常的错误信息;System.out.println(completableFuture.whenComplete((t, u) -> {System.out.println("t=>" + t);// 正常的返回结果System.out.println("u=>" + u);// 错误信息:}).exceptionally((e) -> {System.out.println(e.getMessage());return 233;// 可以获取到错误的返回结果}).get());//如果发生了异常,get可以获取到exceptionally返回的值;}
}
JMM 理解
对 volatile 的理解
1、保证可见性
import java.util.concurrent.*;public class test {// 如果不加volatile 程序会死循环// 加了volatile是可以保证可见性的private volatile static Integer number = 0;//main线程public static void main(String[] args) {//子线程1new Thread(()->{while (number==0){}}).start();try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}//子线程2new Thread(()->{while (number==0){}}).start();try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}number=1;System.out.println(number);}
}
2、不保证原子性
public class test {private static volatile int number = 0;public static void add() {number++;//++ 不是一个原子性操作,是 2~3 个操作}public static void main(String[] args) {//理论上number == 20000for (int i = 1; i <= 20; i++) {new Thread(() -> {for (int j = 1; j <= 1000; j++) {add();}}).start();}//main gcwhile (Thread.activeCount() > 2) {Thread.yield(); //yield让出计算资源并重新竞争资源}System.out.println(Thread.currentThread().getName() + ",num=" + number);//每次都不一样}
}
javap -c test.class
反编译字节码文件:
import java.util.concurrent.atomic.AtomicInteger;public class test {// 这些类的底层都直接和操作系统挂钩,是在内存中修改值。private static volatile AtomicInteger number = new AtomicInteger();public static void add(){//number++;number.incrementAndGet(); //底层是 CAS 保证的原子性}public static void main(String[] args) {//理论上number=20000for (int i = 1; i <= 20; i++) {new Thread(()->{for (int j = 1; j <= 1000 ; j++) {add();}}).start();}//main gcwhile (Thread.activeCount()>2){Thread.yield();}System.out.println(Thread.currentThread().getName()+",num="+number);}
}
3、禁止指令重排
源代码 –> 编译器优化重排 –> 指令并行也可能会重排 –> 内存系统也会重排 –> 执行
int x=1; //1
int y=2; //2
x=x+5; //3
y=x*x; //4//期望的执行顺序是 1_2_3_4 可能执行的顺序会变成2134 1324
volatile 可以避免指令重排:volatile 中会加一道内存的屏障,这个内存屏障可以保证在这个屏障中的指令顺序。
对 JMM 的理解
JMM:Java内存模型,不存在的东西,是一个概念,也是一个约定。
关于 JMM 的一些同步的约定:
- 1、线程解锁前,必须把共享变量立刻刷回主存
- 2、线程加锁前,必须读取主存中的最新值到工作内存中
- 3、加锁和解锁是同一把锁
线程中分为工作内存、主内存。
8种操作:(读read
,加载load
)(使用use
,赋值assign
)(写write
,存储store
)(加锁lock
,解锁unlock
)
内存交互操作有8种,虚拟机实现必须保证每一个操作都是原子的,不可在分的(对于 double 和 long 类型的变量来说,load、store、read 和 write 操作在某些平台上允许例外)
- read(读取):作用于主内存变量,它把一个变量的值从主内存传输到线程的工作内存中,以便随后的load动作使用;
- load(载入):作用于工作内存的变量,它把read操作从主存中变量放入工作内存中;
- use(使用):作用于工作内存中的变量,它把工作内存中的变量传输给执行引擎,每当虚拟机遇到一个需要使用到变量的值,就会使用到这个指令;
- assign(赋值):作用于工作内存中的变量,它把一个从执行引擎中接受到的值放入工作内存的变量副本中;
- store(存储):作用于主内存中的变量,它把一个从工作内存中一个变量的值传送到主内存中,以便后续的write使用;
- write(写入):作用于主内存中的变量,它把store操作从工作内存中得到的变量的值放入主内存的变量中;
- lock(锁定):作用于主内存的变量,把一个变量标识为线程独占状态;
- unlock(解锁):作用于主内存的变量,它把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定;
JMM对这八种指令的使用,制定了如下规则:
- 不允许 read 和 load、store 和 write 操作之一单独出现,必须成对使用。即使用了 read 必须 load,使用了store 必须 write
- 不允许线程丢弃他最近的 assign 操作,即工作变量的数据改变了之后,必须告知主存
- 不允许一个线程将没有 assign 的数据从工作内存同步回主内存
一个新的变量必须在主内存中诞生,不允许工作内存直接使用一个未被初始化的变量。就是怼变量实施 use、store操作之前,必须经过 assign 和 load 操作 - 一个变量同一时间只有一个线程能对其进行 lock。多次 lock 后,必须执行相同次数的 unlock 才能解锁
- 如果对一个变量进行 lock 操作,会清空所有工作内存中此变量的值,在执行引擎使用这个变量前,必须重新 load 或 assign 操作初始化变量的值
- 如果一个变量没有被 lock,就不能对其进行 unlock 操作。也不能unlock一个被其他线程锁住的变量对一个变量进行 unlock 操作之前,必须把此变量同步回主内存
详解单例模式
饿汉式
//饿汉式单例
public class Hungry {//一上来就实例化,可能会浪费空间private byte[] data1 =new byte[1024*1024];private byte[] data2 =new byte[1024*1024];private byte[] data3 =new byte[1024*1024];private byte[] data4 =new byte[1024*1024];//私有化构造器private Hungry() {}private final static Hungry HUNGRY = new Hungry();public Hungry getInstance() {return HUNGRY;}
}
懒汉式
// 懒汉式单例
public class LazyMan {//构造器私有化private LazyMan() {System.out.println(Thread.currentThread().getName()+"OK");}private static LazyMan lazyMan;public static LazyMan getInstance() {if (lazyMan == null) {lazyMan = new LazyMan();}return lazyMan;}//多线程并,会有隐患!public static void main(String[] args) {for (int i = 0; i < 10; i++) {new Thread(()->{lazyMan.getInstance();}).start();}}
}
DCL懒汉式:双重检测锁模式的懒汉式单例
// 懒汉式 DCL单例
public class LazyMan {// 构造器私有化private LazyMan() {System.out.println(Thread.currentThread().getName() + "OK");}// 加volatile,防止指令重排private volatile static LazyMan lazyMan;// 双重检测锁模式的 懒汉式单例 DCL懒汉式public static LazyMan getInstance() {// 第一次检查if (lazyMan == null) {synchronized (LazyMan.class) {// 第二次检查if (lazyMan == null) {lazyMan = new LazyMan();/*** 1. 分配内存空间* 2、执行构造方法,初始化对象* 3、把这个对象指向这个空间* 执行顺序123,132都有可能* A:123 B:132* B把这个对象指向这个空间,发现不为空执行return* 但是此时在线程A中,lazyMan还没有完成构造,lazyMan要加volatile,防止指令重排*/}}}return lazyMan;}//多线程并发public static void main(String[] args) {for (int i = 0; i < 10; i++) {new Thread(() -> {lazyMan.getInstance();}).start();}}
}
静态内部类实现单例
public class Singleton {private static class SingletonHolder {private static final Singleton INSTANCE = new Singleton();}private Singleton() {}public static Singleton getInstance() {return SingletonHolder.INSTANCE;}
}
通过反射破坏单例,修改后的DCL饿汉式
// 懒汉式单例
public class LazyMan {private volatile static LazyMan lazyMan;//私有化构造器private LazyMan() {synchronized (LazyMan.class) {if (lazyMan != null) {throw new RuntimeException("不要试图使用反射破坏异常");}}System.out.println(Thread.currentThread().getName() + "OK");}// 双重检测锁模式的 懒汉式单例 DCL懒汉式public static LazyMan getInstance() {if (lazyMan == null) {synchronized (LazyMan.class) {if (lazyMan == null) {lazyMan = new LazyMan();// 不是一个原子性操作}}}return lazyMan;}//多线程并发public static void main(String[] args) throws Exception {LazyMan instance = LazyMan.getInstance();Constructor<LazyMan> declaredConstructor = LazyMan.class.getDeclaredConstructor(null);declaredConstructor.setAccessible(true);//无视私有LazyMan instance2 = declaredConstructor.newInstance();System.out.println(instance);System.out.println(instance2);}
}
//可以继续破坏
枚举实现单例防止反射破坏
import java.lang.reflect.Constructor;// enum 本身也是一个 Class 类
public enum EnumSingle {INSTANCE;public EnumSingle getInstance(){return INSTANCE;}
}class Test{public static void main(String[] args) throws Exception {EnumSingle instance1 = EnumSingle.INSTANCE;//java.lang.NoSuchMethodException: com.zzy.single.EnumSingle.<init>() 没有空参构造方法//Constructor<EnumSingle> declaredConstructor = EnumSingle.class.getDeclaredConstructor(null);//反编译中,只有有参构造方法 EnumSingle(String s, int i) //java.lang.IllegalArgumentException: Cannot reflectively create enum objectsConstructor<EnumSingle> declaredConstructor = EnumSingle.class.getDeclaredConstructor(String.class,int.class);declaredConstructor.setAccessible(true);EnumSingle instance2 = declaredConstructor.newInstance();System.out.println(instance1);System.out.println(instance2);}
}
理解 CAS(compareAndSwap)
CAS : compareAndSet 比较并交换
import java.util.concurrent.atomic.AtomicInteger;public class test {//CAS : compareAndSet 比较并交换public static void main(String[] args) {AtomicInteger atomicInteger = new AtomicInteger(2020);//boolean compareAndSet(int expect, int update)//期望值、更新值//如果实际值 和 期望值相同,那么就更新//如果实际值 和 期望值不同,那么就不更新System.out.println(atomicInteger.compareAndSet(2020, 2021));System.out.println(atomicInteger.get());//因为期望值是2020 实际值却变成了2021 所以会修改失败//CAS 是CPU的并发原语atomicInteger.getAndIncrement(); //++操作System.out.println(atomicInteger.compareAndSet(2020, 2021));System.out.println(atomicInteger.get());}
}
CAS : compareAndSet 比较并交换源码:
public class AtomicInteger extends Number implements java.io.Serializable {private static final long serialVersionUID = 6214790243416807050L;// Java无法操作内存,C++可以,Java通过native方法调用C++// Java通过Unsafe类操作内存 private static final Unsafe unsafe = Unsafe.getUnsafe();private static final long valueOffset;static {try {// 获取内存地址的偏移值valueOffset = unsafe.objectFieldOffset(AtomicInteger.class.getDeclaredField("value"));} catch (Exception ex) { throw new Error(ex); }}private volatile int value;...public final boolean compareAndSet(int expect, int update) {return unsafe.compareAndSwapInt(this, valueOffset, expect, update);}public final int getAndIncrement() {return unsafe.getAndAddInt(this, valueOffset, 1);}
// 内存操作,效率很高
// 自旋锁
// Unsafe类 unsafe.getAndAddInt(this, valueOffset, 1)
// var1 = this; var2 = valueOffset; var4 = 1public final int getAndAddInt(Object var1, long var2, int var4) {int var5;do {// 获取内存地址valueOffset中的值 var5 = this.getIntVolatile(var1, var2);} while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));// while中:如果当前对象var1中的内存地址偏移值var2,这个值如果还等于var5,那么这个值等于var5+var4return var5;}
CAS 出现的 ABA 问题
CAS:比较当前工作内存中的值和主内存中的值,如果这个值是期望的,那么则执行操作,如果不是就一直循环,使用的是自旋锁。
缺点:
- 循环会耗时
- 一次性只能保证一个共享变量的原子性
- 存在ABA问题
理解 ABA 问题
狸猫换太子:
- 线程1:期望值是1,要变成2;
- 线程2:两个操作:
1、期望值是1,变成3
2、期望是3,变成1
所以对于线程1来说,A的值还是1,所以就出现了问题,骗过了线程1
import java.util.concurrent.atomic.AtomicInteger;public class test {// CAS compareAndSet : 比较并交换public static void main(String[] args) {AtomicInteger atomicInteger = new AtomicInteger(2020);//public final boolean compareAndSet(int expect, int update)// 如果我期望的值达到了,那么就更新,否则,就不更新, CAS 是CPU的并发原语!// ============== 捣乱的线程 ==================System.out.println(atomicInteger.compareAndSet(2020, 2021));System.out.println(atomicInteger.get());System.out.println(atomicInteger.compareAndSet(2021, 2020));System.out.println(atomicInteger.get());// ============== 期望的线程 ==================System.out.println(atomicInteger.compareAndSet(2020, 77777));System.out.println(atomicInteger.get());}
}
解决 ABA 问题(带版本号的原子操作、乐观锁思想)
解决 ABA 问题:引入原子引用,对应的思想:乐观锁。
思想:带版本号的原子操作
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicStampedReference;public class test {//AtomicStampedReference 注意,如果泛型是一个包装类,注意对象的引用问题,正常在业务操作,这里面比较的都是一个个对象static AtomicStampedReference<Integer> atomicStampedReference = newAtomicStampedReference<>(1, 1);// CAS compareAndSet : 比较并交换public static void main(String[] args) {new Thread(() -> {// 获得版本号int stamp = atomicStampedReference.getStamp();System.out.println("a1版本号=>" + stamp);try {TimeUnit.SECONDS.sleep(1);} catch (InterruptedException e) {e.printStackTrace();}// 修改操作时,版本号更新 + 1atomicStampedReference.compareAndSet(1, 2,atomicStampedReference.getStamp(),atomicStampedReference.getStamp() + 1);System.out.println("a2版本号=>" + atomicStampedReference.getStamp());// 重新把值改回去, 版本号更新 + 1System.out.println(atomicStampedReference.compareAndSet(2, 1,atomicStampedReference.getStamp(),atomicStampedReference.getStamp() + 1));System.out.println("a3版本号=>" + atomicStampedReference.getStamp());}, "a").start();// 乐观锁的原理相同!new Thread(() -> {// 获得版本号int stamp = atomicStampedReference.getStamp();System.out.println("b1=>" + stamp);try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(atomicStampedReference.compareAndSet(1, 3,stamp, stamp + 1));System.out.println("b2=>" + atomicStampedReference.getStamp());}, "b").start();}
}
公平锁,非公平锁
- 公平锁: 非常公平, 不能够插队,必须先来后到
- 非公平锁:非常不公平,可以插队 (默认都是非公平)
// ReentrantLock 源码
public class ReentrantLock implements Lock, java.io.Serializable {...public ReentrantLock() {sync = new NonfairSync();}public ReentrantLock(boolean fair) {sync = fair ? new FairSync() : new NonfairSync();}...
}
可重入锁(递归锁)
拿到外面的锁之后,就可以自动获得拿到里面的锁
//Synchronized
public class test {public static void main(String[] args) {Phone phone = new Phone();new Thread(() -> {phone.sms();}, "A").start();new Thread(() -> {phone.sms();}, "B").start();}
}class Phone {//外面一把锁public synchronized void sms() {System.out.println(Thread.currentThread().getName() + ":sms");//里面一把锁call();}public synchronized void call() {System.out.println(Thread.currentThread().getName() + ":call");}
}
//一定是
/*
A:sms
A:call
B:sms
B:call
*/
Lock 锁必须配对,相当于 lock 和 unlock 必须数量相同,在外面加的锁,也可以在里面解锁;在里面加的锁,在外面也可以解锁
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;//Lock
public class test {public static void main(String[] args) {Phone2 phone = new Phone2();new Thread(() -> {phone.sms();}, "A").start();new Thread(() -> {phone.sms();}, "B").start();}
}class Phone2 {Lock lock = new ReentrantLock();public void sms() {lock.lock();try {System.out.println(Thread.currentThread().getName() + ":sms");//里面还有锁call();} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}public void call() {lock.lock();try {System.out.println(Thread.currentThread().getName() + ":call");} catch (Exception e) {e.printStackTrace();} finally {lock.unlock();}}
}
自旋锁
import java.util.concurrent.atomic.AtomicReference;//自旋锁
public class SpinlockDemo {//初始: int -> 0; 引用类型 Thread -> nullAtomicReference<Thread> atomicReference = new AtomicReference<>();// 加锁public void myLock() {Thread thread = Thread.currentThread();System.out.println(Thread.currentThread().getName() + "==> myLock");//自旋锁while (!atomicReference.compareAndSet(null, thread)) {}}// 解锁public void myUnlock() {Thread thread = Thread.currentThread();System.out.println(Thread.currentThread().getName() + "==> myUnlock");//自旋锁atomicReference.compareAndSet(thread, null);}
}
import java.util.concurrent.TimeUnit;public class TestSpinLock {public static void main(String[] args) {//ReentrantLock
/* ReentrantLock reentrantLock = new ReentrantLock();reentrantLock.lock();reentrantLock.unlock();*/// 底层使用的自旋锁 CASSpinlockDemo lock = new SpinlockDemo();new Thread(()->{lock.myLock();try {TimeUnit.SECONDS.sleep(3);} catch (Exception e) {e.printStackTrace();} finally {lock.myUnlock();}},"T1").start();new Thread(()->{lock.myLock();try {TimeUnit.SECONDS.sleep(1);} catch (Exception e) {e.printStackTrace();} finally {lock.myUnlock();}},"T2").start();}
}
/*
T1==> myLock
T2==> myLock //必须等T1解锁,自旋
T1==> myUnlock
T2==> myUnlock
*/
排除死锁
A、B各持有锁,试图获取对方的锁,例如:
import java.util.concurrent.TimeUnit;public class test {public static void main(String[] args) {String lockA = "lockA";String lockB = "lockB";new Thread(new MyThread(lockA, lockB), "T1").start();new Thread(new MyThread(lockB, lockA), "T2").start();}
}class MyThread implements Runnable {private String lockA;private String lockB;public MyThread(String lockA, String lockB) {this.lockA = lockA;this.lockB = lockB;}@Overridepublic void run() {synchronized (lockA) {System.out.println(Thread.currentThread().getName() + "lock: " + lockA + "=> get: " + lockB);try {TimeUnit.SECONDS.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}synchronized (lockB) {System.out.println(Thread.currentThread().getName() + "lock: " + lockB + "=>get: " + lockA);}}}
}
使用 jstack 进程号
,找到死锁问题,进程号由 jps -l
得到
...
"T2":at JUC_learn.MyThread.run(test.java:36)- waiting to lock <0x053bedc8> (a java.lang.String)- locked <0x053bedf0> (a java.lang.String)at java.lang.Thread.run(Thread.java:745)
"T1":at JUC_learn.MyThread.run(test.java:36)- waiting to lock <0x053bedf0> (a java.lang.String)- locked <0x053bedc8> (a java.lang.String)at java.lang.Thread.run(Thread.java:745)Found 1 deadlock.
相关文章:

【JUC基础】JUC入门基础(二)
目录 异步回调JMM 理解对 volatile 的理解1、保证可见性2、不保证原子性3、禁止指令重排 对 JMM 的理解 详解单例模式饿汉式懒汉式DCL懒汉式:双重检测锁模式的懒汉式单例静态内部类实现单例通过反射破坏单例,修改后的DCL饿汉式枚举实现单例防止反射破坏 …...

Git Bash 和 Git GUI中文汉化
目录 为什么要中文汉化?Git Bash的汉化Git GUI的汉化 为什么要中文汉化? 看到中文大概能猜出是什么意思,便于使用,特别是Git GUI,中文版的菜单很容易理解是要做什么,如下图: Git Bash的汉化 …...

【Ubuntu】Ubuntu常用软件部署
1.安装jdk1.8 (1).apt方式安装 1).安装 1.在终端中输入以下命令,以更新软件包列表 sudo apt-get update2.在终端中输入以下命令,以安装JDK 1.8 sudo apt-get install openjdk-8-jdk3.将Java 1.8设置为默认版本。在终端中输入以下命令 sudo update-…...

Hadoop HA模式切换
Hadoop HA模式下 主从的切换(操作命令) YARN HA 获取所有RM节点的状态 yarn rmadmin -getAllServiceState获取 rm1 节点的状态 yarn rmadmin -getServiceState rm1手动将 rm1 的状态切换到STANDBY yarn rmadmin -transitionToStandby rm1 ##或者 y…...

自然语言处理(四):全局向量的词嵌入(GloVe)
全局向量的词嵌入(GloVe) 全局向量的词嵌入(Global Vectors for Word Representation),通常简称为GloVe,是一种用于将词语映射到连续向量空间的词嵌入方法。它旨在捕捉词语之间的语义关系和语法关系&#…...

Flink中RPC实现原理简介
前提知识 Akka是一套可扩展、弹性和快速的系统,为此Flink基于Akka实现了一套内部的RPC通信框架;为此先对Akka进行了解 Akka Akka是使用Scala语言编写的库,基于Actor模型提供一个用于构建可扩展、弹性、快速响应的系统;并被应用…...

ELK安装、部署、调试(五)filebeat的安装与配置
1.介绍 logstash 也可以收集日志,但是数据量大时太消耗系统新能。而filebeat是轻量级的,占用系统资源极少。 Filebeat 由两个主要组件组成:harvester 和 prospector。 采集器 harvester 的主要职责是读取单个文件的内容。读取每个文件&…...

Python数据分析案例30——中国高票房电影分析(爬虫获取数据及分析可视化全流程)
案例背景 最近总看到《消失的她》票房多少多少,《孤注一掷》票房又破了多少多少..... 于是我就想自己爬虫一下获取中国高票房的电影数据,然后分析一下。 数据来源于淘票票:影片总票房排行榜 (maoyan.com) 爬它就行。 代码实现 首先爬虫获…...

科技资讯|苹果Vision Pro头显申请游戏手柄专利和商标
苹果集虚拟现实和增强现实于一体的头戴式设备 Vision Pro 推出一个月后,美国专利局公布了两项苹果公司申请的游戏手柄专利,其中一项的专利图如下图所示。据 PatentlyApple 报道,虽然专利本身并不能保证苹果公司会推出游戏手柄,但是…...

Compose学习 - remember、mutableStateOf的使用
一、需求 在显示界面中,数据变动,界面刷新是非常常见的操作,所以使用compose该如何实现呢? 二、remember、mutableStateOf的使用 我们可以借助标题的两个概念 remember、mutableStateOf来完成。这里先不写定义,定义…...

字符串哈希
字符串前缀哈希法 str "ABCABCDEHGJK" 预处理每一个前缀的哈希值,如 : h[0] 0; h[1] "A"的哈希值 h[2] "AB"的哈希值 h[3] "ABC"的哈希值 h[4] "ABCA"的哈希值 问题 : 如何定义一个前缀的哈希值 : 将字符串看…...

【python】【centos】使用python杀死进程后自身也会退出
问题 使用python杀死进程后自身程序也会退出,无法执行后边的代码 这样不行: # cmd " ps -ef | grep -v grep | grep -E task_pull_and_submit.py$|upgrade_system.py$| awk {print $2}"# pids os.popen(cmd).read().strip(\n).split(\n)# p…...

【ES系列】(一)简介与安装
首发博客地址 首发博客地址[1] 系列文章地址[2] 教学视频[3] 为什么要学习 ES? 强大的全文搜索和检索功能:Elasticsearch 是一个开源的分布式搜索和分析引擎,使用倒排索引和分布式计算等技术,提供了强大的全文搜索和检索功能。学习 ES 可以掌…...

opencv案例06-基于opencv图像匹配的消防通道障碍物检测与深度yolo检测的对比
基于图像匹配的消防通道障碍物检测 技术背景 消防通道是指在各种险情发生时,用于消防人员实施营救和被困人员疏散的通道。消防法规定任何单位和个人不得占用、堵塞、封闭消防通道。事实上,由于消防通道通常缺乏管理,导致各种垃圾࿰…...

练习2:88. 合并两个有序数组
这里写自定义目录标题 题目解体思路代码 题目 给你两个按非递减顺序排列的整数数组 nums1 和 nums2,另有两个整数 m和 n ,分别表示 nums1 和 nums2中的元素数目。 请你合并nums2 到 nums1 中,使合并后的数组同样按非递减顺序排列。 注意&a…...

【代码随想录day23】不同路径
题目 一个机器人位于一个 m x n 网格的左上角 (起始点在下图中标记为 “Start” )。 机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角(在下图中标记为 “Finish” )。 问总共有多少条不同的路径? 示…...

SpringBoot 博客网站
SpringBoot 博客网站 系统功能 登录注册 博客列表展示 搜索 分类 个人中心 文章分类管理 我的文章管理 发布文章 开发环境和技术 开发语言:Java 使用框架: SpringBoot jpa H2 Spring Boot是一个用于构建Java应用程序的开源框架,它是Spring框架的一…...

【分布式搜索引擎elasticsearch】
文章目录 1.elasticsearch基础索引和映射索引库操作索引库操作总结 文档操作文档操作总结 RestAPIRestClient操作文档 1.elasticsearch基础 什么是elasticsearch? 一个开源的分布式搜索引擎,可以用来实现搜索、日志统计、分析、系统监控等功能 什么是…...

wireshark 流量抓包例题
一、题目一(1.pcap) 题目要求: 1.黑客攻击的第一个受害主机的网卡IP地址 2.黑客对URL的哪一个参数实施了SQL注入 3.第一个受害主机网站数据库的表前缀(加上下划线例如abc) 4.第一个受害主机网站数据库的名字 看到题目SQL注入,…...

【Axure视频教程】表格编号函数
今天教大家在Axure里如何使用表格编号函数,包括表格编号函数的基本原理、在需要翻页的中继器表格里如何正确使用该函数、函数作为条件的应用,包括让指定第几行的元件默认变色效果以及更新对应第几行内容的效果。该教程主要讲解表格编号函数,不…...

大数据-玩转数据-Flink定时器
一、说明 基于处理时间或者事件时间处理过一个元素之后, 注册一个定时器, 然后指定的时间执行. Context和OnTimerContext所持有的TimerService对象拥有以下方法: currentProcessingTime(): Long 返回当前处理时间 currentWatermark(): Long 返回当前watermark的时间戳 registe…...

Linux 操作系统实战视频课 - GPIO 基础介绍
文章目录 一、GPIO 概念说明二、视频讲解沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇我们将讲解 GPIO 。 一、GPIO 概念说明 ARM 平台中的 GPIO(通用输入/输出)是用于与外部设备进行数字输入和输出通信的重要硬件接口。ARM 平台的 GPIO 特性可以根据具体的芯…...

ChatGPT在医疗保健信息管理和电子病历中的应用前景如何?
ChatGPT在医疗保健信息管理和电子病历中有着广阔的应用前景,可以提高医疗保健行业的效率、准确性和可访问性。本文将详细讨论ChatGPT在医疗保健信息管理和电子病历中的应用前景,以及相关的益处和挑战。 ### 1. ChatGPT在医疗保健信息管理中的应用前景 …...

安防监控/视频存储/视频汇聚平台EasyCVR接入海康Ehome车载设备出现收流超时的原因排查
安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等,以及支持厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。视频汇聚平台既具…...

【zookeeper】zookeeper监控指标查看
zookeeper 监控指标 日常工作中,我们有时候需要对zookeeper集群的状态进行检查,下面分享一些常用的方法。 zookeeper获取监控指标已知的有两种方式: 通过zookeeper自带的四字命令 (four letter words command )获取各…...

Flink 如何处理反压?
分析&回答 什么是反压(backpressure) 反压通常是从某个节点传导至数据源并降低数据源(比如 Kafka consumer)的摄入速率。反压意味着数据管道中某个节点成为瓶颈,处理速率跟不上上游发送数据的速率,而…...

JAVA基础-JDBC
本博客记录JAVA基础JDBC部分的学习内容 JDBC基本概念 JDBC : JAVA链接数据库,是JAVA链接数据库的技术的统称,包含如下两部分: 1. JAVA提供的JDBC规范(即各种数据库接口)存储在java.sql 和 javax.sql中的api 2. 各个数…...

嵌入式学习笔记(1)ARM的编程模式和7种工作模式
ARM提供的指令集 ARM态-ARM指令集(32-bit) Thumb态-Thumb指令集(16-bit) Thumb2态-Thumb2指令集(16 & 32 bit) Thumb指令集是对ARM指令集的一个子集重新编码得到的,指令长度为16位。通常在…...

[NSSCTF Round #15NSSCTF 2nd]——Web、Misc、Crypto方向 详细Writeup
前言 虽然师傅们已经尽力了,但是没拿到前十有点可惜,题很好吃,明年再来() 关于wp: 因为我没有学过misc,但是比赛的时候还是运气好出了三道,所以wp就只把做题步骤给出,也…...

Metasploit“MSF”连接postgresql时因排序规则版本不匹配导致无法连接
一、问题 更新Kali之后使用Metasploit时出现一个问题,连接postgresql时因排序规则版本不匹配导致无法连接 警告: database "msf" has a collation version mismatch DETAIL: The database was created using collation version 2.36, but the operati…...