多线程(基础)

  前言👀~

上一章我们介绍了什么是进程,对于进程就了解那么多即可,我们作为java程序员更关注线程,线程内容比较多,所以我们要分好几部分才能讲完

目录

进程的缺点

 多线程(重要)

进程和线程的区别(经典面试题)

java如何进行多线程编程?

创建线程的方式(面试题)

继承Thread类(来自java.lang包下)

使用匿名内部类继承Thread类重写run

实现Runnable接口

使用匿名内部类实现Runnable接口重写run

使用lambda表达式创建线程(推荐)

Thread 类及常见方法

Thread类的构造方法

Thread类的常见属性

启动线程

中断线程

等待线程

查看线程状态


如果各位对文章的内容感兴趣的话,请点点小赞,关注一手不迷路,如果内容有什么问题的话,欢迎各位评论纠正 🤞🤞🤞

12b46cd836b7495695ce3560ea45749c.jpeg

个人主页:N_0050-CSDN博客

相关专栏:java SE_N_0050的博客-CSDN博客  java数据结构_N_0050的博客-CSDN博客  java EE_N_0050的博客-CSDN博客


进程的缺点

多进程编程的缺点:进程太重量效率不高,创建进程和销毁进程和调度进程消耗的时间都是比较多的(消耗在申请资源上),因为我们知道进程是系统资源分配的基本单元,所以在给进程分配资源的时候是一个大活。拿分配内存说,操作系统内部也有一定的数据结构,用来管理空闲的内存,当进程申请内存空间的时候,操作系统就会从这个数据结构中找到大小合适空闲的内存返回给进程。这里的数据结构可以提高一定的效率,但是总体来说和线程相比还是比较耗时的。同时频繁创建和销毁进程和进程切换是一个开销很大的操作,多进程和多线程都能实现并发编程,线程比进程更轻量。有些任务场景需要 “等待 IO”, 为了让等待 IO 的时间能够去做⼀些其他的工作, 也需要用到并发编程. 其次,虽然多进程也能实现 并发编程, 但是线程比进程更轻量


 多线程(重要)

进程想要执行任务就需要依赖线程线程不能独立存在,需要依附于进程(进程包含线程,进程可包含一个线程也可包含多个线程),一个进程在最开始的时候,至少要有一个线程(主线程),这个线程负责完成执行代码的工作,我们也可以根据需要创建多个线程,从而实现"并发编程"的效果换句话说,就是进程中的最小执行单位就是线程

线程也称轻量级线程(创建、销毁、调度都比进程快),每个线程就是一个独立的 "执行流"(因为在执行用户写的代码)可以独立的执行一些代码,每一个线程可以执行一系列的操作(也就是代码)

更好的理解线程,还是拿之前在进程举的演员的例子,一个舞台可以有多个演员,但是呢这个多个演员来自不同的剧组,这里面的演员就是线程,剧组就是进程。在我们之前谈的进程调度都是基于一个进程只有一个线程,可以理解为之前每个剧组都只有一个演员。实际上,一个进程可以有多个线程,每个线程都可以独立进行调度。之后谈到进程调度的话,不是调度整个进程,而是调度进程中的每一个线程。就比如说这个导演叫这个剧组的所有人来拍戏,所有的演员由导演进行分配角色、上场时间、台词等,相当于线程也有状态、优先级、上下文、记账信息

下面有图更好理解多线程
 
一个工厂代表一个进程,一个生产线代表一个线程,我们之前提到的多进程是下面这样子的 


下面这样是我们说的多线程,一个进程中有多个线程,同个工厂(共用资源)两个生产线(多线程)提高了效率


下面这么多人吃100个坤,适当的线程数目(里面的人)能提高效率,但是线程数目过多的情况,效率会降低并且造成线程冲突(线程不安全)


当人数过多且有人吃不到坤的时候,生气了把鸡全扔了,此时引发线程异常,如果我们没有处理好,可能会导致整个进程崩了,其他线程也会随之消失


总结:一个进程使用PCB来表示,一个进程可以使用一个PCB表示也可与使用多个PCB表示,每个TCB对应一个线程(可以理解PCB中包含TCB),并且每个线程都有这些信息(状态、优先级、上下文、记账信息,但每个线程有自己的程序计数器、虚拟机栈和本地方法栈)辅助调度,除此之外,前面说到的属性pid是相同的,内存指针、文件描述符表也是共用一份的,根据这些信息我们可以得出线程的特点:每个线程都可以独立去cpu上调度执行、同一个线程的多个进程之间共用一份内存空间和文件资源,所以我们创建线程的时候不需要像进程一样申请资源(但是呢创建第一个线程的时候,相当于和进程一起创建的,所以我们要去申请资源,这里申请资源算在进程头上。后续再创建线程的话就是共享同一份了),我们直接用系统给进程分配好的资源,这样大大提高了我们的效率和节省开销。综上所述我们可以得出进程是资源分配的基本单位,线程是CPU 调度执行的基本单位

每个线程都是独立调度的,在调度的过程中,系统就不考虑 进程 这样的概念了。所以就是不同进程中的线程可以被轮番调度,每个线程只有获得 CPU 的使用权才能执行指令。所谓多线程的并发运行,其实是指从宏观上看,各个线程轮流获得 CPU 的使用权,分别执行各自的任务。


进程和线程的区别(经典面试题)

1.线程比进程更轻量、高效,线程不需要申请资源,和同一进程共用一份,省去了申请资源的开销

2.同一个进程内线程和线程之间会有影响(线程不安全和线程异常),一个线程崩了可能导致其他线程受到影响最终导致进程崩了。进程和进程之间具有独立性

3.线程依附于进程,一个进程至少有一个线程(主线程),也可以有多个线程

4.线程是调度执行的基本单位,进程是资源分配的基本单位


java如何进行多线程编程?

线程是操作系统的概念,操作系统提供了一套API来操作线程,java对操作系统提供的API进行封装(跨平台),我们学java的只需要掌握java封装过后的这套API就可以操作线程了

进程和进程之间能并发执行实现并发编程,线程和线程之间也能实现并发执行实现并发编程,我们学java的更侧重线程之间的并发执行

创建线程的方式(面试题)

继承Thread类(来自java.lang包下)

创建Thread对象,我们就可以操作 操作系统内部的线程了。以及重写入口方法run(描述了该线程要执行的任务)

class MyThread extends Thread {@Overridepublic void run() {System.out.println("我开始工作了");System.out.println("我结束工作了");}
}public class test1 {public static void main(String[] args) {Thread thread = new MyThread();thread.start();System.out.println("我是主线程");}
}

输出:不确定

再来看下面这段代码,猜一下输出顺序

class MyThread extends Thread {@Overridepublic void run() {while (true) {System.out.println("thread线程正在工作");}}
}public class test1 {public static void main(String[] args) {Thread thread = new MyThread();thread.start();while (true) {System.out.println("主线程正在工作");}}
}

输出:交替输出


为什么呢?我们也不知道这两个线程是同时执行的还是交替执行的(同一个核心上执行,还是分别在两个核心上执行),所以我们统称并发(并行+并发),实现并发编程的效果,为什么要实现并发编程?(充分利用多核cpu的资源)。

注意:打印顺序不一定,操作系系统对于多个线程的调度顺序是不确定的,随机的。虽然有先后顺序但是谁先谁后我们是不确定的(重要),这个随机取决于操作系统对于线程调度的模块(调度器)的具体实现

接着再来看下面这段代码,猜一下输出顺序

class MyThread extends Thread {@Overridepublic void run() {while (true) {System.out.println("thread线程正在工作");}}
}public class test1 {public static void main(String[] args) {Thread thread = new MyThread();thread.run();while (true) {System.out.println("主线程正在工作");}}
}

输出:thread线程正在工作   不只一条哈

原因:T.run 这种时候只有一个主线程,因为我们没有创建一个新的进程。等run这个方法结束后,才会执行后面的代码,相当于只有一个执行流,只能依次执行循环。相当于就是main线程在执行它的run方法,就跟我们在main方法中平常创建一个类然后调用方法一样,main线程在工作

不信的话代码拿去自己试试,然后用jdk中自带的工具jconsole,里面其他线程是JVM创建的

使用匿名内部类继承Thread类重写run

同样创建Thread对象,我们就可以操作 操作系统内部的线程了。以及重写入口方法run(描述了该线程要执行的任务)

public class test1 {public static void main(String[] args) {Thread thread = new Thread() {@Overridepublic void run() {System.out.println("我是匿名内部类");}};thread.start();System.out.println("我是主线程");}
}

实现Runnable接口

实现Runnable接口,它就表示的是一个可以运行的任务,所以还是需要创建线程来完成这个任务。这样理解我写了个任务,丢给线程去完成,但是我们要先把线程创建出来才能去完成

class MyRunnable implements Runnable {@Overridepublic void run() {while (true) {System.out.println("我是Runnable接口");}}
}public class test1 {public static void main(String[] args) {MyRunnable myRunnable = new MyRunnable();Thread thread = new Thread(myRunnable);thread.start();while (true) {System.out.println("主线程正在工作");}}
}

使用Runnable接口和继承Thread类的区别:主要是为了解耦合,使用Runnable接口相当于跟线程拆分开,把任务抽离出来,可以把这个任务丢给任意一个线程去完成,可以用在需要重复完成这个任务的场景,直接继承Thread类就不行,它更适合完成一次性的任务

还有关于创建一个线程的时候,有两个关键的操作。一个是明确线程要执行的任务,我们更关注任务本身,如果这个任务就只是执行一段简单的代码至于用什么方式实现这个任务没什么区别。如果遇到复杂的任务有些方式可能就完成不了,这时候我们需要用其他的方式去完成,这时候我们把任务提取出来,我们可以自己选择指定的方式去完成这个任务    。另外一个操作就是通过调用系统API创建出线程。

使用匿名内部类实现Runnable接口重写run

public class test1 {public static void main(String[] args) {Thread thread = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("我是匿名内部类");}}) {};thread.start();System.out.println("我是主线程");}
}

使用lambda表达式创建线程(推荐)

public class test1 {public static void main(String[] args) {Thread thread = new Thread(() -> {System.out.println("我是lambda表达式");});thread.start();System.out.println("我是主线程");}
}

除了上面的方式之外,还有其他的方式,后续讲解,还有一个点需要清楚就是创建Thread类的时候并没有真正创建线程,只有在调用start方法的时候调用系统API去创建线程的时候才算认识


Thread 类及常见方法

Thread类的构造方法

在Thread类源码里有个构造方法可以设置线程的名字,其他的就没什么好介绍的了

public class test1 {public static void main(String[] args) {Thread thread = new Thread(() -> {while (true) {System.out.println("我是lambda表达式");}}, "我叫线程A");thread.start();}
}

为什么这里没有显示main线程呢?因为main线程执行完了,线程的入口方法执行完了,这个线程自然就销毁了。对于主线程来说,入口方法就是main方法,它调用系统API去创建完线程之后就执行完了。所以如果线程都执行完了,进程也就结束了但只要有一个线程还在执行,进程就不会结束
 


Thread类的常见属性


1.ID:线程的身份标识就是用来区分线程的,类似进程的pid,只不过这里的ID是java提供的,不是系统api提供的

2.getState()方法:获取线程状态,后面有讲到

3.isDaemon()方法判断是否为后台线程(守护线程),守护线程就是用来告诉JVM,我的这个线程不重要不需要等待它运行完才退出,让JVM喜欢什么时候退出就退出。前台线程(非守护线程)就是告诉JVM,这个线程没执行完成之前,你不能退出。默认情况一个线程是前台线程守护进程(后台进程),默认情况一个线程是前台线程我们可以通过setDameon()方法去设置,这么设置之后主线程执行完后,没有其他前台线程了,这个进程自然也就结束了

public class test1 {public static void main(String[] args) {Thread thread = new Thread(() -> {while (true) {System.out.println("我是lambda表达式");}}, "我叫线程A");thread.setDaemon(true);//设置thread线程为守护线程thread.start();}
}

4.isAlive()方法:Thread对象的生命周期要比系统内核中的线程更长,线程没了Thread对象还在,我们要以系统内核中的线程为主。所以我们使用isAlive()进行判断,判断系统内核中的线程有没有结束,结束返回false,没结束返回true。简单的理解为 run 方法是否运行结束了

public class test1 {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("我是lambda表达式");}, "我叫线程A");System.out.println(thread.isAlive());thread.start();System.out.println(thread.isAlive());Thread.sleep(2000);System.out.println(thread.isAlive());}
}

输出:false true 我是lambda表达式 false

5.isInterrupted()方法:用来判断线程是否被中断,怎么判断呢?Thread内部有一个标志位进行判断。下面会讲到


启动线程

使用start()方法创建线程

start方法和run方法的区别:非常直白的说,你可以把run看作是任务,start是叫人过来完成这个任务的。专业点说就是start方法通过调用系统API在系统内核中创建线程然后执行run方法中的代码。run方法会在线程创建好后自动被被调用


中断线程

中断一个线程(终止/打断),让一个线程停止运行(销毁),在java中销毁/终止一个线程做法比较唯一(这个唯一不是说只有一个方法,而是说销毁一个进程是让run方法快点执行完),让run方法快点执行完。在C++中是可以直接强制终止一个线程的运行,就比如你打开一个文本编辑器输入一段信息,输入一半直接给你干没了

先补充两个方法currentThread()方法和sleep()方法后面要用到

获取当前线程引用:currentThread()方法返回当前线程对象的引用,哪个线程调用这个方法就获取哪个线程对象的引用

休眠当前线程:sleep()方法让线程睡觉的,你可以设置睡多久,然后时间到了系统把它叫醒(阻塞->就绪),注意睡醒之后不会马上回到cpu上运行,要排队,这里会涉及调度所以会有一定的开销。就是你睡醒了需要一点时间缓缓才能去工作。

interrupt()方法:使用interrupt()方法设置标志位,前面说了Thread内部有一个标志位用来判断线程是否结束,调用这个方法就把这个标志位设置成true。这样即使我们还在执行sleep方法,它也会被强制唤醒。

来猜猜下面执行代码线程会是什么状态以及输出什么

public class test1 {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {while (!Thread.currentThread().isInterrupted()) {System.out.println("hello");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});thread.start();Thread.sleep(3000);thread.interrupt();}
}

答案是输出几个hello后报异常,然后说说过程,这个线程先执行sleep方法,然后这个线程处于睡眠,然后你使用了interrupt()方法设置把标志位为true,把这个线程唤醒了,那么这个线程就会继续工作,除非你不让它睡眠并且设置标志位为true。举个例子本来你在上班,然后突然有点困了,你同事让你睡会,结果领导来了你同事赶紧把你叫醒,你立马起来了。

使用interrupt()方法搭配sleep方法这样设置的标志位就像没效果一样,没有把你的线程中断,为什么这样设定呢?java期望线程收到中断的信息的时候,我们能够自己决定接下来要怎么处理,这样可以让我们在开发中有更多的操作空间,前提是通过异常的方式去唤醒。比如你打游戏女朋友叫你陪她去逛街,你可以直接关掉游戏陪她去,也可以说等我打完这把,还可以当个聋子啥也没听见。

public class test1 {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {while (!Thread.currentThread().isInterrupted()) {System.out.println("hello");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();
//            第一种   System.out.println("一直工作");
//                    
//            第二种   System.out.println("工作一会休息了");
//                    break;
//                    
//            第三种   break;}}});thread.start();Thread.sleep(3000);thread.interrupt();}
}

等待线程

使用join()方法,让一个线程等待另外一个线程执行结束再执行。前面说线程并发执行的时候,执行的顺序是不确定的随机的,此时我们可以通过这个方法来控制线程结束的顺序。并且我们可以设置等待时间,如果没有设置等待时间,默认的话这个线程会一直等到那个线程执行结束后才会执行自己的任务,类似舔狗有一直舔的也有舔一段时间不舔了

join方法的工作过程:

1.如果主线程正在运行,主线程中调用了A.join方法,此时主线程进入阻塞状态,A线程执行完,主线程才会解除完成接下来的任务

public class test1 {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {for (int i = 0; i < 5; i++) {System.out.println("我先干完活,你再干");}});thread.start();System.out.println("我要干活了");thread.join();System.out.println("轮到我干活了");}
}

输出结果

2.如果主线程任务已经执行完了,再调用A.join方法,就不用进入阻塞状态了,直接结束了

public class test1 {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {for (int i = 0; i < 5; i++) {System.out.println("我先干完活,你再干");}});thread.start();System.out.println("我马上干完不给你机会干");thread.join();}
}

输出结果


查看线程状态

和进程一样,线程也有运行、就绪、阻塞状态。真正在系统调度的还是线程,线程是调度执行的基本单位

在java中,给线程赋予了一些其他的状态:

1.NEW:Thread对象已经存在了,但是系统线程还没创建,也就是还没调用start方法

2.RUNNABLE:就绪状态,这里有两种表示,一种是在cpu上执行了,另一种是正等着去cpu上执行

3.TIMED_WATING:阻塞,被sleep这种固定时间的方式打断产生的阻塞

4.WATING:阻塞,被wait这种不固定时间的方式打断产生的阻塞

5.BLOCKED:阻塞,等待锁导致的阻塞,后续死锁讲解

6.TERMINATED:Thread对象还在,操作系统内核的线程结束了,也这样理解意味着该线程已经完成了其run方法的执行

public class test1 {public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {while (!Thread.currentThread().isInterrupted()) {System.out.println("java");try {Thread.sleep(2000);} catch (InterruptedException e) {break;}}});System.out.println(t.getState());//只创建了Thread对象的NEW状态t.start();System.out.println(t.getState());//创建完线程t就是这个RUNNABLE状态Thread.sleep(1000);System.out.println(t.getState());//t线程处于睡眠t.interrupt();Thread.sleep(1000);System.out.println(t.getState());//t线程执行完了}
}

输出结果

后续线程出现卡死的情况,我们可以通过上述后面三种状态去确定卡死的原因是什么,最后两个状态后续再讲解

上述方法是多线程中非常常用的方法,要好好掌握,今天的内容就先到这,后面我们接着讲解线程还有不少的知识点等着💕

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

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

相关文章

鸿蒙开发Ability Kit(程序框架服务):【FA模型切换Stage模型指导】 module的切换

module的切换 从FA模型切换到Stage模型时&#xff0c;开发者需要将config.json文件module标签下的配置迁移到module.json5配置文件module标签下&#xff0c;具体差异见下列表格。 表1 FA模型module标签与Stage模型module标签差异对比 FA标签标签说明对应的Stage标签差异说明…

LeetCode刷题之HOT100之课程表

吃完普通的食堂饭菜&#xff0c;回到实验室&#xff0c;继续做一道题&#xff01; 1、题目描述 2、逻辑分析 这道题涉及到图相关知识&#xff0c;应用到了拓扑排序。 题意解释 一共有 n 门课要上&#xff0c;编号为 0 ~ n-1。先决条件 [1, 0]&#xff0c;意思是必须先上课 0…

触动心弦的成语之旅:《米小圈动画成语》带你走进中华智慧

成语&#xff0c;这些古老而典雅的语言精华&#xff0c;如同中华文化的晶莹明珠&#xff0c;闪耀着历史的光辉和智慧的火花。从古至今&#xff0c;它们在中国人的日常交流中扮演着重要角色&#xff0c;不仅传递着深刻的哲理和文化内涵&#xff0c;更是凝聚了世代智者的思想和智…

【Linux】线程id与互斥(线程三)

上一期我们进行了线程控制的了解与相关操作&#xff0c;但是扔就有一些问题没有解决 本章第一阶段就是解决tid的问题&#xff0c;第二阶段是进行模拟一个简易线程库&#xff08;为了加深对于C库封装linux原生线程的理解&#xff09;&#xff0c;第三阶段就是互斥。 目录 线程id…

链在一起怎么联机 链在一起远程同玩联机教程

steam中最近特别热门的多人跑酷冒险的游戏&#xff1a;《链在一起》&#xff0c;英文名称叫做Chained Together&#xff0c;在游戏中我们需要开始自己的旅程&#xff0c;在地狱的深处&#xff0c;与我们的同伴被链在一起。我们的任务是通过尽可能高的攀登逃离地狱。每一次跳跃都…

Python第三方库GDAL 安装

安装GDAL的方式多种&#xff0c;包括pip、Anaconda、OSGeo4W等。笔者在安装过程中&#xff0c;唯独使用pip安装遇到问题。最终通过轮子文件&#xff08;.whl&#xff09;成功安装。 本文主要介绍如何下载和安装较新版本的GDAL轮子文件。 一、GDAL轮子文件下载 打开Github网站…

Python学习打卡:day16

day16 笔记来源于&#xff1a;黑马程序员python教程&#xff0c;8天python从入门到精通&#xff0c;学python看这套就够了 目录 day16116、SQL 基础和 DDLSQL的概述SQL语言的分类SQL的语法特征DDL — 库管理DDL — 表管理 117、SQL — DMLDML概述数据插入 INSERT数据删除 DEL…

深入理解 Dubbo:分布式服务框架的核心原理与实践

目录 Dubbo 概述Dubbo 的架构Dubbo 的关键组件 服务提供者&#xff08;Provider&#xff09;服务消费者&#xff08;Consumer&#xff09;注册中心&#xff08;Registry&#xff09;监控中心&#xff08;Monitor&#xff09;调用链追踪&#xff08;Trace&#xff09; Dubbo 的…

专题页面设计指南:从构思到实现

如何设计专题页&#xff1f;你有什么想法&#xff1f;专题页的设计主要以发扬产品优势为核心。一个好的专题页可以从不同的角度向用户介绍产品&#xff0c;扩大产品的相关优势&#xff0c;表达产品的优势&#xff0c;让用户在短时间内了解产品。因此&#xff0c;在设计详细信息…

纯血鸿蒙Beta版本发布,中国华为,站起来了!

2024年6月21日至23日&#xff0c;华为开发者大会2024&#xff08;HDC 2024&#xff09;于东莞盛大举行。 此次大会不仅在会场设置了包括鸿蒙原生应用、统一生态统一互联等在内的11个展区&#xff0c;以供展示HarmonyOS NEXT的强大实力&#xff0c;还对外宣布了HarmonyOS的最新进…

240627_关于CNN中图像维度变化问题

240627_关于CNN中图像维度变化问题 在学习一些经典模型时&#xff0c;其中得维度变化关系总搞不太明白&#xff0c;集中学习了以下&#xff0c;在此作以梳理总结&#xff1a; 一般来说涉及到的维度变换都是四个维度&#xff0c;当batch size4&#xff0c;图像尺寸为640*640&a…

kylin v10 离线安装chrome centos离线安装chrome linux离线安装谷歌浏览器

1. 先用自己联网的计算机&#xff0c;下载离线安装包&#xff0c;浏览器输入链接下载安装包&#xff1a; https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm 1.2. 信创环境不用执行下面&#xff0c;因为没网 1.3. 若为阿里云服务器&#xff0c;或服…

AR导航技术加持,图书馆阅读体验智慧升级

在信息爆炸的今天&#xff0c;图书馆作为知识的宝库&#xff0c;其藏书量和种类日益增多。然而&#xff0c;传统的图书馆导航方式已逐渐无法满足用户对快速、准确定位图书的需求。本文将探讨图书馆AR地图导航的实现原理、技术优势、功能特点以及市场前景&#xff0c;揭示为何AR…

VS studio2019配置远程连接Ubuntu

VS studio2019配置远程连接Ubuntu 1、网络配置 &#xff08;1&#xff09;获取主机IP &#xff08;2&#xff09;获取Ubuntu的IP &#xff08;3&#xff09;在 windows 的控制台中 ping 虚拟机的 ipv4 地址&#xff0c;在 Ubuntu 中 ping 主机的 ipv4 地址。 ubuntu: ping…

【Linux】对共享库加载问题的深入理解——基本原理概述

原理概述 【linux】详解——库-CSDN博客 共享库被加载后&#xff0c;系统会为该共享库创建一个结构&#xff0c;这个结构体中的字段描述了库的各种属性。在内存中可能会加载很多库&#xff0c;每一个库都用一个结构体描述。把这些结构体用一些数据结构管理起来&#xff0c;系…

WordPress Dokan Pro插件 SQL注入漏洞复现(CVE-2024-3922)

0x01 产品简介 WordPress Dokan Pro插件是一款功能强大的多供应商电子商务市场解决方案,功能全面、易于使用的多供应商电子商务平台解决方案,适合各种规模的电商项目。允许管理员创建一个多卖家平台,卖家可以注册账户并在平台上创建自己的店铺,展示和销售自己的产品。提供…

kali下安装使用蚁剑(AntSword)

目录 0x00 介绍0x01 安装0x02 使用1. 设置代理2. 请求头配置3. 编码器 0x00 介绍 蚁剑&#xff08;AntSword&#xff09;是一个webshell管理工具。 官方文档&#xff1a;https://www.yuque.com/antswordproject/antsword 0x01 安装 在kali中安装蚁剑&#xff0c;分为两部分&am…

Zabbix 监控系统部署

Zabbix 监控系统部署 Zabbix是一个企业级开源分布式监控解决方案&#xff0c;可监控网络的众多参数以及服务器、虚拟机、应用程序、服务、数据库、网站、云等的运行状况和完整性。 Zabbix 使用灵活的通知机制&#xff0c;允许用户为几乎任何事件配置基于电子邮件的警报。这允许…

java发送图文到公众号

这两天接到了一个新任务&#xff0c;通过后台管理编写文章&#xff0c;发送到官网的同时&#xff0c;推送一份到公众号&#xff0c;研究了一下微信的文档&#xff0c;发现不难&#xff0c;只需要有几个注意点就可以了。 注意&#xff1a; 微信公众号只能访问微信自己上传的图片…

STM32单片机实现串口IAP升级

一.概述 1.要实现串口IAP升级&#xff0c;首先要编写一个bootloader程序&#xff0c;然后再写支持IAP的app程序&#xff1b; 2.keil下bootloader的程序rom和ram设置 3.app程序要用bin文件 注&#xff1a;本文以STM32H743举例&#xff0c;其他stm32单片机IAP升级原理类似。 …