进程,线程,并发相关入门

进程与线程的简单理解

进程是一个独立的执行单元,它拥有自己的内存空间文件句柄和系统资源.进程是操作系统层面的,每个应用运行就是一个进程.进程之间通常是隔离的,它们不能直接访问对方的内存空间,必须通过进程间通信(IPC)机制来进行数据交换。

线程是进程内的执行单元,归属于进程,它共享进程的内存空间和资源。一个进程可以包含多个线程。但至少需要一个(普通)线程存活(守护线程不算).

并行与并发:

并行概念:并行是指多个进程或者多个线程同时执行任务,只是看起来并行,事实上没有真正的并行(暂时不存在真正意义上的并行,以后不知道).只是人类的感官觉得是并行.(即多核CPU中央处理器也无法达到真正并行)其实都是走走停停

并发:并发是指在相同的时间段内处理多个任务或操作的能力。这并不一定意味着这些任务实际上是同时执行的,而是它们在某个时间间隔内交替执行,以创建一种错觉,似乎它们在同时进行。可以是线程,也可以是进行,一般是指多个线程同时抢占同一个资源,导致错误结果.俗称并发安全问题

创建线程的第一种方式继承Thread,重写run方法

public class Thread1 {public static void main(String[] args) {Thread t1=new MyThread1();Thread t2=new MyThread2();t1.start();t2.start();}
}
//第一种方式:继承线程
class MyThread1 extends Thread{@Overridepublic void run() {for(int i=0;i<100;i++){System.out.println("你是谁呀");}}
}
class MyThread2 extends Thread{@Overridepublic void run() {for(int i=0;i<100;i++){System.out.println("查水表的");}}
}

局部内部类写法

public class Thread1 {public static void main(String[] args) {Thread t1=new Thread(){@Overridepublic void run() {for(int i=0;i<100;i++){System.out.println("你是谁呀");}}};Thread t2=new Thread(){@Overridepublic void run() {for(int i=0;i<100;i++){System.out.println("你是谁呀");}}};t1.start();t2.start();}
}

匿名内部类写法

public class Thread1 {public static void main(String[] args) {new Thread(){@Overridepublic void run() {for(int i=0;i<100;i++){System.out.println("你是谁呀");}}}.start();new Thread(){@Overridepublic void run() {for(int i=0;i<100;i++){System.out.println("你是谁呀");}}}.start();}
}

继承Thread的优点是写起来方便(特别是匿名内部类方式),缺点是Java是单继承的.继承了Thread之后无法再继承其他类.

第二点是线程和线程要干的活有着强耦合关系

创建线程的第二种方式.实现Runable接口.定义线程要执行的任务,将任务交给线程去执行

public class Thread2 {public static void main(String[] args) {//创建任务MyRunable1 my1=new MyRunable1();MyRunable2 my2=new MyRunable2();//创建线程 并让线程启动任务Thread t1=new Thread(my1);Thread t2=new Thread(my2);t1.start();t2.start();}
}
class MyRunable1 implements Runnable{@Overridepublic void run() {for(int i=0;i<100;i++){System.out.println("你是谁呀");}}
}
class MyRunable2 implements Runnable{@Overridepublic void run() {for(int i=0;i<100;i++){System.out.println("查水表的");}}
}

内部类写法

public class Thread2 {public static void main(String[] args) {//创建线程 并让线程启动任务Thread t1=new Thread(new Runnable(){@Overridepublic void run() {for(int i=0;i<100;i++){System.out.println("你是谁呀");}}});Thread t2=new Thread(new Runnable() {@Overridepublic void run() {for(int i=0;i<100;i++){System.out.println("查水表的");}}});t1.start();t2.start();}
}

匿名内部类写法

public class Thread2 {public static void main(String[] args) {//创建线程 并让线程启动任务new Thread(new Runnable(){@Overridepublic void run() {for(int i=0;i<100;i++){System.out.println("你是谁呀");}}}).start();new Thread(new Runnable() {@Overridepublic void run() {for(int i=0;i<100;i++){System.out.println("查水表的");}}}).start();}
}

CurrentThread方法介绍:获取当前运行的线程

public class Thread3 {public static void main(String[] args) {/*** 线程提供了一个静态方法* static Thread currentThread()* 该方法用来获取运行这个方法的线程* main方法也是靠一个线程运行的.当JVM启动* 后会自动创建一个线程来执行main方法.称之为主线程*/Thread thread = Thread.currentThread();System.out.println(thread);//Thread[main,5,main]dosome();Thread t1=new Thread(){@Overridepublic void run() {Thread t = Thread.currentThread();System.out.println("运行dosome方法的线程:"+t);//Thread[Thread-0,5,main]}};Thread t2=new Thread(){@Overridepublic void run() {Thread t = Thread.currentThread();System.out.println("运行dosome方法的线程:"+t);//Thread[Thread-1,5,main]}};t1.start();t2.start();}public static void dosome(){Thread thread = Thread.currentThread();System.out.println("运行dosome方法的线程:"+thread);//谁调用就是谁}
}

线程相关信息的获取

//线程提供了获取自身信息的相关方法
public class Thread4 {public static void main(String[] args) {//获取线程名Thread thread = Thread.currentThread();String name = thread.getName();System.out.println("name:"+name);//获取线程的唯一标识(id)   线程名可以重  但是id不能重long id = thread.getId();System.out.println("该线程的id是:"+id);Thread t1=new Thread(){@Overridepublic void run() {Thread t = Thread.currentThread();System.out.println("运行dosome方法的线程:"+t);//Thread[Thread-0,5,main]System.out.println("该线程的id是:"+t.getId());}};Thread t2=new Thread(){@Overridepublic void run() {Thread t = Thread.currentThread();System.out.println("运行dosome方法的线程:"+t);//Thread[Thread-0,5,main]System.out.println("该线程的id是:"+t.getId());}};t1.start();t2.start();//获取线程的优先级  1到10之间  默认都是5int priority = thread.getPriority();System.out.println("主线程的优先级:"+priority);boolean alive = thread.isAlive();System.out.println("线程是否还活者:"+alive);boolean interrupted = thread.isInterrupted();//中断就是让线程停了 一旦线程被中断(使用 interrupt() 方法中断),它的生命周期结束,不能重新启动.等待垃圾回收器回收System.out.println("线程是否被中断:"+interrupted);//守护线程或称之为后台线程boolean daemon = thread.isDaemon();System.out.println("线程是否为守护线程:"+daemon);}
}

一个个讲上面提到的方法

首先线程优先级 int priority = thread.getPriority();  1到10之间  默认都是5

线程优先级作用:干涉线程调度器工作 只能理论上尽量让该线程多获得CPU时间片,但是实际情况,说不好
理论上:线程优先级越高,获得CPU时间片的次数越多. 优先级用整数表示: 10最高    1最低    默认5

大于10或者小于1都会报错

理论来讲应该是优先级高的先输出完,然后是默认的,然后是优先级最低的,但是实际效果是不一定

调整线程优先级的结果未必理想,但是这是唯一可以改变争取或降低CPU时间片的方式

//线程优先级
public class PriorityDemo {public static void main(String[] args) {//线程优先级作用:干涉线程调度器工作 只能理论上尽量让该线程多获得CPU时间片,但是实际情况,说不好//理论上:线程优先级越高,获得CPU时间片的次数越多. 优先级用整数表示: 10最高    1最低    默认5Thread max=new Thread(){@Overridepublic void run() {for(int i=0;i<10000;i++){System.out.println("max");}}};Thread min=new Thread(){@Overridepublic void run() {for(int i=0;i<10000;i++){System.out.println("min");}}};Thread norm=new Thread(){@Overridepublic void run() {for(int i=0;i<10000;i++){System.out.println("norm");}}};//如果设置的优先级>最高(10) 或者<(1)都会报错   抛IllegalArgumentException//max.setPriority(10);max.setPriority(Thread.MAX_PRIORITY);//用常量   设置优先级min.setPriority(Thread.MIN_PRIORITY);norm.setPriority(Thread.NORM_PRIORITY);max.start();min.start();norm.start();}
}

sleep阻塞

线程提供了一个静态方法:static void sleep(long ms)

使运行这个方法的线程阻塞指定毫秒.超时后该线程会自动回到Runnable状态,

等待再次获得CPU时间片运行 这个和计时器差不多

public class Thread5 {public static void main(String[] args) {System.out.println("程序开始了");try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("程序结束了");}
}

小案例:控制太输入倒计,每个1秒,到0停止

java中一般会引起线程阻塞的方法都要求捕获InterruptedException中断异常

public class Thread6 {public static void main(String[] args) {System.out.println("输入数字:");Scanner scanner=new Scanner(System.in);String line = scanner.nextLine();Integer num=Integer.parseInt(line);for(;num>0;num--){System.out.println(num);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("结束");}
}

sleep阻塞demo2

sleep方法要求必须处理中断异常,原因在于当一个线程调用了sleep方法处于阻塞状态的过程中其他线程中若调用了它的interupt()方法中断时,它就会在sleep方法中抛出中断异常.这时并非是将这个线程直接中断,而是中断了它的阻塞状态.

  

public class Thread7 {public static void main(String[] args) {Thread lin=new Thread(){@Overridepublic void run() {//while(!Thread.currentThread().isInterrupted()) {System.out.println("林:刚美完容,睡一觉");try {Thread.sleep(10000000);} catch (InterruptedException e) {System.out.println("林:干嘛呢?干嘛呢?");}//}System.out.println("林:醒了");}};Thread huang=new Thread(){@Overridepublic void run() {System.out.println("黄:开始砸墙!");for(int i=0;i<5;i++){System.out.println("黄:80!");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("咣当!");System.out.println("黄:搞定!");//中断lin线程lin.interrupt();//这里注意:JDK8之前这样写报错,报错原因JDK8之前要求局部内部类中要使用方法内的局部变量,那个变量前要加final}};lin.start();huang.start();}
}

守护线程

守护线程又称后台线程,默认创建的线程都是普通线程或称为前台线程,线程提供了一个

方法:void setDaemon(boolean on)

只有调用该方法并传入为true时,该线程才会被设置为守护线程.

守护线程在使用上于普通线程没有差别,但是在结束时机上有一个区别,即:线程结束时所有正在运行的守护线程都会被强制停止.

进程的结束:当一个进程中所有的普通线程都结束时,进程即结束

GC就是一个守护线程

public class Thread8 {public static void main(String[] args) {Thread rose=new Thread(){@Overridepublic void run() {for(int i=0;i<5;i++){System.out.println("rose:let me go!");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("rose:啊啊啊啊啊啊啊啊啊!!!!!");}};Thread jack=new Thread(){@Overridepublic void run() {while(true){System.out.println("jack:you jump! I jump!");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}};Thread disanzhe=new Thread(){@Overridepublic void run() {for(int i=0;i<10;i++) {System.out.println("disanzhe:吃瓜!看热闹");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}}};rose.start();jack.setDaemon(true);//设置为守护线程,要在启动前设置  有几个线程启动就守护几个线程jack.start();disanzhe.start();//原先的观点:main方法结束,程序退出.以后的观点就是:当所有前台线程结束,进程结束.才算结束System.out.println("main方法结束");//这里是main先结束//这样的话,守护线程永远不会结束,原因是main线程还一致活者
//        while(true){
//
//        }}
}

join:协调线程之间的同步运行

线程提供了一个方法:

void join()

该方法可以协调线程之间的同步运行

同步与异步:

同步:运行有顺序

异步运行:运行代码无顺序,多线程并发运行就是异步运行

多线程是异步运行的,但是有时候我们也需要他们同步---->利用join

public class Thread9 {private static boolean isFinish=false;//这个放在方法内编译不通过public static void main(String[] args) {int a=1;Thread download=new Thread(){@Overridepublic void run() {System.out.println("down:开始下载图片");for(int i=1;i<=100;i++){System.out.println("down:"+i+"%");try {Thread.sleep(200);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("down:下载图片完毕");isFinish=true;}};Thread show=new Thread(){@Overridepublic void run() {System.out.println("show:开始显示图片");//加载图片前应先等待下载线程将图片下载完毕try {/*** show线程里调用download.join()方法后* 就进入了阻塞状态,知道download线程的run方法执行完毕才会解除*///这样可以使用应该和线程上下文有关download.join();//在show的线程里写  download.join() 就是等待download线程完毕} catch (InterruptedException e) {e.printStackTrace();}if(!isFinish){throw new RuntimeException("加载图片失败");}System.out.println("show:显示图片完毕");}};download.start();show.start();}
}

wait    用锁对象.wait()

wait()方法其实主要做三件事:

①把当前线程放进等待队列中

②释放锁

③被其他线程唤醒时,尝试重新获取锁

wait() 无参数版本

wait(long) 指定最大等待时间,单位毫秒

wait(long,int) 精度更高,前面是毫秒,后面是纳秒

notifyAll():唤醒加了相同锁的所有线程

wait和sleep其实是没有可比性的,因为一个是用于线程之间的通信的,一个是让线程阻塞一段时间。这两个方法设计的初心是不同的,一个是单纯为了让线程进行阻塞等待而休眠一段时间,而一个是为了解决线程的执行顺序的问题。最明显的区别就是wait需要搭配锁使用,而sleep不需要。wait 是 Object 的方法 sleep 是 Thread 的静态方法。他们唯一的相同点就是都可以让线程进入阻塞等待状态。
 

但是自测sleep无法唤醒,只能interrupt中断(不是很清楚)

notify:用锁对象.notify() 唤醒

public class Thread7 {public static void main(String[] args) {Object o=new Object();Thread lin=new Thread(){@Overridepublic void run() {//while(!Thread.currentThread().isInterrupted()) {System.out.println("林:刚美完容,睡一觉");synchronized (o) {try {//Thread.sleep(1000000);o.wait();} catch (InterruptedException e) {System.out.println("林:干嘛呢?干嘛呢?");}}//}System.out.println("林:醒了");}};Thread huang=new Thread(){@Overridepublic void run() {System.out.println("黄:开始砸墙!");for(int i=0;i<5;i++){System.out.println("黄:80!");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}System.out.println("咣当!");System.out.println("黄:搞定!");//唤醒该锁线程,可以在线程里,方法里synchronized (o){o.notify();}//中断lin线程//lin.interrupt();//这里注意:JDK8之前这样写报错,报错原因JDK8之前要求局部内部类中要使用方法内的局部变量,那个变量前要加final}};lin.start();huang.start();}
}
public class Thread10 {public static void main(String[] args) throws InterruptedException {Object lock = new Object();Thread thread1 = new Thread(() -> {synchronized (lock) {try {lock.wait();System.out.println("Thread1被唤醒了");} catch (InterruptedException e) {e.printStackTrace();System.out.println("出错了");}}});Thread thread2 = new Thread(() -> {synchronized (lock) {try {lock.wait();System.out.println("Thread2被唤醒了");} catch (InterruptedException e) {e.printStackTrace();System.out.println("出错了");}}});thread1.start();thread2.start();Thread.sleep(5000);synchronized (lock){//lock.notify();lock.notifyAll();}}
}

并发安全问题

并发会出现的情况

多线程并发的安全问题

产生:当多个线程并发操作同一资源时,由于线程切换时机的不确定性,会导致

执行操作资源的代码顺序未按照设计顺序执行,出现操作混乱的情况.

严重时可能导致系统瘫痪.

解决:将并发操作同一资源改为同步操作,即:有先后顺序的操作

public class SyncDemo1 {public static void main(String[] args) {Table table=new Table();Thread t1=new Thread(){@Overridepublic void run() {while(true){int bean=table.getBean();Thread.yield();System.out.println(getName()+":"+bean);}}};Thread t2=new Thread(){@Overridepublic void run() {while(true){int bean=table.getBean();Thread.yield();System.out.println(getName()+":"+bean);}}};t1.start();t2.start();}
}
class Table{//20个豆子private int bean=20;public int getBean(){if(bean==0){throw new RuntimeException("没有豆子了");}//模拟线程执行到这里没有时间了 它是告诉线程调度器,愿意主动让出CPU时间片,不能确保线程一定会让出Thread.yield();return bean--;}
}

解决办法:加同步锁

在getBean方法上加锁 synchronized   对方法枷锁  就是给对象枷锁

但是在方法上加上synchronized会降低效率

那么用同步块缩小控制范围

同步块:语法

synchronized(同步监视器对象){

        需要同步运行的代码片段

}

同步块可以更精准的控制需要同步运行的代码片段.有效的缩小同步范围可以在保证并发安全

的前提下提高代码并发运行的效率

使用同步块控制多线程同步运行必须要求这些线程看到的同步监视器对象为[同一个]

有效缩小同步范围可以在保证

public class SyncDemo2 {public static void main(String[] args) {Shop shop=new Shop();Thread t1=new Thread(){@Overridepublic void run() {shop.buy();}};Thread t2=new Thread(){@Overridepublic void run() {shop.buy();}};t2.start();}
}
class Shop{public void buy(){try {Thread t=Thread.currentThread();System.out.println(t.getName()+":正在挑衣服");Thread.sleep(5000);synchronized (this) {System.out.println(t.getName() + ":正在试衣服");Thread.currentThread();}System.out.println(t.getName()+":结账离开");} catch (InterruptedException e) {e.printStackTrace();}}
}

静态方法加synchronized一定具有同步效果,锁的是类对象 Class的实例

当静态方法加了synchronized,已经和对象无关了,无论你创建了多少个对象,

必定会有同步效果

public class SyncDemo3 {public static void main(String[] args) {Foo f1=new Foo();Foo f2=new Foo();Thread t1=new Thread(){@Overridepublic void run() {//Foo.dosome();f1.dosome();}};Thread t2=new Thread(){@Overridepublic void run() {//Foo.dosome();f2.dosome();}};t1.start();t2.start();}
}
class Foo{public synchronized static void dosome(){Thread t=Thread.currentThread();System.out.println(t.getName()+":正在运行dosome方法");try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(t.getName()+":运行dosome方法完毕");}
}

synchronized的另外一种作用:

synchronized称为同步锁,还可以帮助维护一种关系,互斥关系

有你没我,有我没你.比如有A方法和B方法,我们希望出现的情况是:

调用A方法就不能调用B,调用B方法就不能调用A,就是不能同时干两个方法

比如咽下去东西和喘气就是互斥的,不能同时干

如何在程序里实现互斥关系,希望互斥的代码用synchronized锁上,然后互斥的代码使用的锁是同一个,他们之间就是互斥关系

互斥锁:

当多个代码片段被synchronized块修饰后,这些同步块的同步监听器对象又是同一个时,这些代码片段就是互斥的.多个线程不能同时在这些方法中运行.

注意:不一定是两个方法,可以是两个代码块,只要锁的对象是同一个,就有互斥效果

public class SyncDemo4 {public static void main(String[] args) {Boo boo=new Boo();Thread t1=new Thread(){@Overridepublic void run() {boo.methodA();}};Thread t2=new Thread(){@Overridepublic void run() {boo.methodA();}};t1.start();t2.start();}
}
class Boo{public synchronized void methodA(){Thread t=Thread.currentThread();try {System.out.println(t.getName()+":正在运行A方法");Thread.sleep(5000);System.out.println(t.getName()+":运行A方法结束");} catch (InterruptedException e) {e.printStackTrace();}}public synchronized void methodB(){Thread t=Thread.currentThread();try {System.out.println(t.getName()+":正在运行B方法");Thread.sleep(5000);System.out.println(t.getName()+":运行B方法结束");} catch (InterruptedException e) {e.printStackTrace();}}
}

关于Thread的静态方法 static void yield()

该方法用于使当前线程主动让出当次CPU时间片回到Runable状态,等待分配时间片

上面这图就是线程运行状态

线程.start()之后进入可运行状态(并不是立刻执行,而是交给线程调度器,进入可运行状态,线程调度器把CPU时间分配给谁,谁先执行,不一定说先start的就一定先执行),当获得CPU时间之后开始运行,CPU时间片用完了,回到可运行状态,等待线程调度分配CPU时间片,任务完成(run方法执行完毕)等待被回收.线程调度器无序分配CPU时间片,只能说尽量分配获得CPU时间片的时间均匀,但不保证

线程有三种阻塞状态,分别是IO阻塞     Sleep阻塞   Wait阻塞  阻塞的直观表现就是卡了

IO阻塞常见的比如说Scanner      Sleep阻塞比如说Thread.sleep  

执行某些特殊代码,让线程进入阻塞状态

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/80204.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

详细解释HiveSQL执行计划

一、前言 Hive SQL的执行计划描述SQL实际执行的整体轮廓&#xff0c;通过执行计划能了解SQL程序在转换成相应计算引擎的执行逻辑&#xff0c;掌握了执行逻辑也就能更好地把握程序出现的瓶颈点&#xff0c;从而能够实现更有针对性的优化。此外还能帮助开发者识别看似等价的SQL其…

前端面试话术集锦第 12 篇:高频考点(Vue常考基础知识点)

这是记录前端面试的话术集锦第十二篇博文——高频考点(Vue常考基础知识点),我会不断更新该博文。❗❗❗ 这一章节我们将来学习Vue的一些经常考到的基础知识点。 1. 生命周期钩子函数 在beforeCreate钩子函数调用的时候,是获取不到props或者data中的数据的,因为这些数据的…

log4j2漏洞复现

log4j2漏洞复现 漏洞原理 log4j2框架下的lookup查询服务提供了{}字段解析功能&#xff0c;传进去的值会被直接解析。例如${sys:java.version}会被替换为对应的java版本。这样如果不对lookup的出栈进行限制&#xff0c;就有可能让查询指向任何服务&#xff08;可能是攻击者部署…

MC-4/11/01/400 ELAU 软件允许用户完全访问相机设置

MC-4/11/01/400 ELAU 软件允许用户完全访问相机设置 一个完整的Sentinel模具保护解决方案包括一到四台冲击式摄像机、专用红外LED照明和镜头、Sentinel软件以及所有与模压机连接的必要互连组件。摄像机支架基于磁性&#xff0c;可快速、安全、灵活地部署。此外&#xff0c;一个…

部署ik分词器

部署ik分词器 案例版本&#xff1a;elasticsearch-analysis-ik-8.6.2 ​ ES默认自带的分词器对中文处理不够友好&#xff0c;创建倒排索引时可能达不到我们想要的结果&#xff0c;然而IK分词器能够很好的支持中文分词 ​ 因为是集群部署&#xff0c;所以每台服务器中的ES都需…

unity 使用Photon进行网络同步

Pun使用教程 第一步&#xff1a;请确保使用的 Unity 版本等于或高于 2017.4&#xff08;不建议使用测试版&#xff09;创建一个新项目。 第二步&#xff1a;打开资源商店并找到 PUN 2 资源并下载/安装它。 导入所有资源后&#xff0c;让 Unity 重新编译。 第三步&#xf…

Python中Mock和Patch的区别

前言&#xff1a; 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! python更多源码/资料/解答/教程等 点击此处跳转文末名片免费获取 在测试并行开发&#xff08;TPD&#xff09;中&#xff0c;代码开发是第一位的。 尽管如此&#xff0c;我们还是要写出开发的测试&#xff0c…

解决SpringMVC在JSP页面取不到ModelAndView中数据

版权声明 本文原创作者&#xff1a;谷哥的小弟作者博客地址&#xff1a;http://blog.csdn.net/lfdfhl 问题描述 ModelAndView携带数据跳转到指定JSP页面后在该页面通过EL表达式取不到原本存放在ModelAndView中的数据。 问题原因 在IDEA中创建Maven工程时web.xml中默认的约束…

医院如何实现安全又稳定的跨网文件数据交换呢?

随着医疗信息化的发展&#xff0c;医院之间需要频繁地进行文件数据交换&#xff0c;以实现诊疗、科研、管理等方面的协同和共享。然而&#xff0c;由于医院网络环境的复杂性和敏感性&#xff0c;跨网文件数据交换面临着安全性和稳定性的双重挑战。如何在保证文件数据不被泄露、…

八、硬改之设备画像

系列文章目录 第一章 安卓aosp源码编译环境搭建 第二章 手机硬件参数介绍和校验算法 第三章 修改安卓aosp代码更改硬件参数 第四章 编译定制rom并刷机实现硬改(一) 第五章 编译定制rom并刷机实现硬改(二) 第六章 不root不magisk不xposed lsposed frida原生修改定位 第七章 安卓…

【leetcode 力扣刷题】栈和队列的基础知识 + 栈的经典应用—匹配

栈和队列的基础知识 栈的经典应用—匹配 栈和队列基础知识232. 用栈实现队列225. 用队列实现栈 20. 有效的括号1047. 删除字符串中的所有相邻重复项 栈和队列基础知识 数据结构课程介绍线性结构的时候&#xff0c;介绍有线性表、链表、栈和队列。线性表&#xff0c;比如array…

【k8s】kube-proxy 工作模式

文章目录 Userspace模式&#xff1a;iptables模式&#xff1a;负载均衡&#xff08;Load Balancing&#xff09; LB轮询&#xff08;Round Robin&#xff09;&#xff1a;SessionAffinity&#xff1a;最少连接&#xff08;Least Connection&#xff09;&#xff1a;IP哈希&…

所有字母异位词

class Solution { public:vector<int> findAnagrams(string s, string p) {std::vector<int> idxs;// 先获取p的hash串std::string dstr getHash(p);for (int i 0; i<s.length(); i) {// 使用滑动窗口&#xff0c;每次截取p的长度串并hashstd::string sub_str…

Acwing 828. 模拟栈

Acwing 828. 模拟栈 题目要求思路讲解代码展示 题目要求 思路讲解 栈&#xff1a;先进后出 队列&#xff1a;先进先出 代码展示 #include <iostream>using namespace std;const int N 100010;int m; int stk[N], tt;int main() {cin >> m;while (m -- ){string o…

企业级数据仓库-数仓实战

数仓实战 安装包大小 安装清单 环境搭建 一、环境搭建01&#xff08;机器准备&#xff09; 准备好三台虚拟机&#xff0c;并进行修改hostname、在hosts文件增加ip地址和主机名映射 。 1、设置每个虚拟机的hostname vi /etc/sysconfig/network 修改HOSTNAMEnode02修改hostna…

将阿里云盘挂载到本地磁盘-CloudDrive工具使用教程

CloudDrive是什么&#xff1f; 支持将115、沃家云盘、天翼云盘、阿里云盘、WebDAV挂载到本地并创建本地磁盘。 CloudDrive是一个全方位的云存储管理平台&#xff0c;旨在无缝集成多个云存储服务&#xff0c;将它们统一整合到一个界面中。 使用CloudDrive&#xff0c;您可以轻松…

Nginx-高性能Web服务器

前言&#xff1a; 平时总听hex说Nginx服务器,也经常找他解决项目上的nginx配置&#xff0c;但自己一直不懂&#xff0c;不懂就学。 听他说&#xff1a;nginx最重要是 location url 配置&#xff08; 正则&#xff09;、反向代理与负载均衡&#xff0c;平时项目用这些比较多。 …

android AudioRecord

AudioRecord是Android中用于音频录制的类&#xff0c;它的主要作用是捕获来自设备麦克风或其他音频源的音频数据&#xff0c;并将其保存为PCM格式的音频流&#xff0c;以供后续处理或存储。 以下是关于AudioRecord的一些常见用途和基本使用方法&#xff1a; 作用和用途&#…

百度千帆大模型文心一言api调用

注册百度智能云账号并申请文心千帆大模型资格 https://login.bce.baidu.com/ https://cloud.baidu.com/product/wenxinworkshop 创建应用用于获取access_token 创建应用成功后,可以获取到API Key和Secret Key 获取access_token curl https://aip.baidubce.com/oauth/2.0/to…

使用电力系统稳定器 (PSS) 和静态 VAR 补偿器 (SVC) 提高瞬态稳定性(Matlab代码实现)

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