网站上线做什么/深圳谷歌网络推广公司
线程
1. 线程
定义
:线程是进程的组成部分,不同的线程执行不同的任务,不同的功能模块,同时线程使用的资源师由进程管理,主要分配CPU和内存。 在进程中,线程执行的方式是抢占式执行操作,需要考虑的是当前的线程是否持有CPU的执行权和等待权,同时关注线程的状态。
多线程
:有了多线程,我们就可以让程序同时处理多个事件。作用能够快速提高效率。
并发和并行的区别
并发:表示的是在同一时刻,多个任务在单个的CPU上的交替执行的操作。并行:表示的是在单位时间内,多个处理器或者多核处理器的同时处理的方式,是真正意义上的同时进行。串行:表示的是有N个任务,通过一个线程进行顺序的执行操作,由于任务中只存在一个任务,方法都是在一个线程的执行的,所以不存在线程的不安全的情况,也就是不存在临界区的问题。比如两个人排队使用一台电脑。
1.1 多线程的优点
有利于提高CPU的利用效率,允许单个程序创建多个并行执行的线程来完成各自的任务
1.2 多线程的缺点
- 线程也是程序,所以线程是需要进行内存的占用的,线程越多,内存的占用越多
- 多线程需要进行协调和管理,所以需要CPU时间跟踪线程
- 线程之间对于共享资源的访问是相互影响的,必须解决竞用共享资源的问题。
1.3 守护线程
守护线程是运行在后台的,为其他的前台的线程提供服务的,也可以说守护线程是JVM中非守护线程的“佣人”一旦所有的线程都结束运行,守护线程会随着JVM进行运行操作。
2. 线程的创建
2.1 通过继承Thread类的方式
Tread类是线程类,一种反方是将类声明为Thread的子类的方式,该子类的应该通过重写run方法的方式来创建线程。
使用的步骤格式:
- 自己定义一个类继承Thread
- 重写run方法
- 创建子类对象,而且进行线程的启动
class MyThread1 extends Thread {@Overridepublic void run() {// 线程代码}
}main() {// 实例化自定义继承 Thread 类子类对象MyThread1 mt1 = new MyThread1();// 利用继承父类 Thread 中的 start 方法,启动线程。【切记不可以直接调用 run 方法】mt1.start();
}
【重点】
为什么我们通过调用start方法来执行run方法,而不是直接调用run方法
- 首先new一个Tread线程,线程进入到新创建的状态中,调用start方法,会启动一个线程并且将线程进入到就绪的状态,当分配到时间片的时候,就能够进行工作了。start() 方法会执行线程的准备工作,然后自己进行执行run() 方法的内容,这才是真正的多线程的工作。
- 直接执行run方法的时候,main方法会将其看做一个普通的反方进行执行操作,并不会在某个线程中去执行它,所以不是多线程的工作。
2.2 通过实现Runnable接口
多线程的创建的步骤:
- 自己定义一个类实现Runnable接口
- 重写里面的run方法
- 创建自己的类对象
- 创建一个Tread类的对象,Runnable作为参数传入,并且开启线程
Runnable 接口是一种函数式接口,@FuncationalInterface ,能够使用lambda表达式。
class MyThread2 implements Runnable {@Overridepublic void run() {// 线程代码}
}main() {/*可以利用 Thread 类构造方法,实例化目标线程对象,执行对应线程目标将 Runnable 接口的实现类对象作为 Thread 构造方法参数构造方法 Thread(Runnable target);构造方法的作用是以 :Runnable 接口实现类为当前线程的执行目标,new 关键字 + 构造方法实例化线程对象*/Thread t1 = new Thread(new MyThread2());t1.start();
}
真实案例的代码实现:class MyThread1 extends Thread {@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println("自定义线程继承 Thread 类型完成线程类");}}}class MyThread2 implements Runnable {@Overridepublic void run() {for (int i = 0; i < 100; i++) {System.out.println("自定义线程遵从 Runnable 接口实现线程类");}}
}/*** Thread 自定义线程类实现的两种方式** @author Anonymous 2023/3/8 10:06*/
public class Demo1 {public static void main(String[] args) {MyThread1 mt1 = new MyThread1();Thread mt2 = new Thread(new MyThread2());mt1.start();mt2.start();for (int i = 0; i < 100; i++) {System.out.println("main方法内容...");}}
}
2.3 通过实现Callable接口(有返回结果)
多线程的第三种的实现的方式:
- 创建一个 自定义 类实现java.util.concurrent包Callable接口
- 重写call方法(
有返回值
,表示的是多线程的运行的结果)- 创建MyCallable的对象(表示多线程要进行执行的任务)
- 创建FutureTask的对象(作用是管理多线程的运行的结果)
- 创建Thread类的对象,并且进行启动的操作(表示线程)
【注意】:其中的callable是存在泛型的格式的,其中的泛型表示的是返回值的泛型
//方法步骤
public class MyCallable implements Callable<Integer> {@Overridepublic Integer call() throws Exception {/** 用来求解1~100 的和*/int sum = 0;for (int i = 0; i <= 100; i++) {sum += i;}return sum;}
}// 测试实现操作
public class TestMain {public static void main(String[] args) throws ExecutionException, InterruptedException {/** 1. 创建MyCallable的对象(表示的是多线程要执行的任务)*/MyCallable myCallable = new MyCallable();/*2. 创建FutureTask的对象,作用是用来管理多线程的运行的结果*/FutureTask<Integer> integerFutureTask = new FutureTask<>(myCallable);/** 3. 创建线程的对象*/Thread thread = new Thread(integerFutureTask);/*4.启动线程*/thread.start();/** 获取多线程的运行的结果*/Integer integer = integerFutureTask.get();System.out.println(integer);}
}
总结
- Tread 继承的操作,编码比较简单,可以直接使用Tread类中的方法,可以拓展的可能性比较差,不能够继承其他的类
- 接口的方式是可拓展性是比较强的,实现接口的同时还可以继承其他的类,编程相对来说比较复杂,不能够直接使用Tread类中方法。
2.4 线程中操作方法
方法名称 | 作用 |
---|---|
String getName() | 获取指定线程对象的名称 |
void setName(String name) | 针对于线程的名称获取和设置 |
int getPriority() | 获取指定线程的优先级 |
void setPriority(int newPriority) | 获取指定线程的优先级 默认是5 只能够提供被执行的概率,不能确保一定会执行操作 |
final void setDaemon(boolean flag) | 设置指定线程为守护线程 |
boolean isDaemon() | 设置和判断当前线程是否为守护线程 |
static void sleep(long time)单位是ms | 强迫一个线程睡眠的时间,单位是毫秒级别的 |
static Thread currentThread(); | 在哪一个线程代码中执行,获取当前线程代码对应的线程对象。 |
static void yield() | 出让线程,礼让线程的操作 |
static void join() | 插入线程、插队线程的操作 |
构造方法:Thread();过Thread(Runnable target);以 Runnable 接口实现类为当前线程的执行目标,new 关键字 + 构造方法实例化线程对象Thread(Runnable target, String threadName);以 Runnable 接口实现类为当前线程的执行目标,同时明确当前线程的名字,new 关键字 + 构造方法实例化线程对象
对于指定的方法进行分析的操作1. String getName() : 表示的是获取指定的线程的名称,如果没有设置名称,线程也会自动生成名称的,通过源码我们能够看到是this当前线程 + nextThreadNum(): 是一个变量的自动递增。2. void setName(String name):对于线程进行名字的设置除了调用方法的设置的方式之外,还能够通过调用构造方法的方式来进行实现:比如说Thread(String threadName) 以及 Thread(Runnable target, String threadName)两种方法来实现线程名称的命名。3.static Tread currentThread() :获取当前线程的对象。细节是:当JVM虚拟机进行启动的时候,会自动的启动多条线程,其中有一条线程是main线程,它的作用是调用main方法,并且执行里面的代码,在以前的时候,我们所写的代码其实都是运行在main线程中4.static void sleep(long time):那条线程执行到这个反方,那么那条线程就会在这里进行停留时间。方法的参数,就表示的是睡眠的时间,时间的单位毫秒。1s = 1000ms 当时间到了之后,线程会自动的醒来,继续执行下面的其他的代码。5.final void setDaemon(boolean flag) 当其他的非守护线程执行完毕之后,守护线程会陆续的结束,既当其他线程结束操作之后,守护线程也就没有存在的必要了。
/**
* 通过实现runnable接口实现线程的创建
*/
public class MyRunnable implements Runnable{@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println(Thread.currentThread().getName()+"____"+i);}}
}
public class Demo1 {public static void main(String[] args) {/** 创建线程需要执行的参数对象*/Runnable runnable = new MyRunnable();/** 创建线程对象*/Thread thread = new Thread(runnable, "张三");Thread thread1 = new Thread(runnable, "李四");/** 通过更改优先级的大小,提高线程优先运行的概率,不能够保证一定是优先执行的操作。*/thread.setPriority(10);thread1.setPriority(6);/** 进行线程的执行的操作,需要进行开启线程操作*/thread.start();thread1.start();}
}运行的结果:
李四____0
张三____0
张三____1
张三____2
张三____3
张三____4
张三____5
张三____6
张三____7
张三____8
张三____9
李四____1
李四____2
李四____3
李四____4
李四____5
李四____6
李四____7
李四____8
李四____9
2.5 线程的生命周期
sleep 方法会让线程睡眠,睡眠的时间到了之后,不会立刻执行下面的代码:
不会
直接执行,会进入到就绪的状态上,然后进行线程资源的抢夺,如果抢夺到资源后能够运行。
3. 线程安全
线程安全的问题:对于线程安全来说,所有的隐患都是出现多个线程访问的情况下产生的,我们能够确保在多条线程访问的情况下,我们的程序能够按照我们预期的行为去执行。
需求:某电影院中目前需要上映国产的大片,共有100张票,需要三个窗口进行售票的行为,请设计一个程序模拟电影院进行买票的行为。
// 采用继承的方式创建对象
/*** 通过继承的方式操作线程*/
public class MyThread extends Thread{/*表示的是这个类中的所有的对象,都在共享tickets的数据*/static int ticket = 0;@Overridepublic void run() {while (true) {if (ticket < 100){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}ticket ++ ;System.out.println(getName()+"正在卖"+ticket+"张票");} else {break;}}}
}// 进行检验
public class Demo1 {/***检验多线程的问题** @param args*/public static void main(String[] args) {/** 1. 创建线程对象*/MyThread myThread1 = new MyThread();MyThread myThread2 = new MyThread();MyThread myThread3 = new MyThread();/*通过调用方法起名字*/myThread1.setName("窗口1");myThread2.setName("窗口2");myThread3.setName("窗口3");/*开启线程的操作*/myThread1.start();myThread2.start();myThread3.start();}
}运行的结果:......
窗口1正在卖96张票
窗口3正在卖97张票
窗口1正在卖99张票
窗口2正在卖99张票
窗口3正在卖100张票
窗口1正在卖101张票
窗口2正在卖102张票分析:出现重复的数据卖出,同时出现数据的溢出操作
总结:在进行循环的时候,出现线程满足循环的条件,所以进行执行的操作,出现线程争夺资源的情况,所以造成的问题是关于线程的安全的问题。
3.1 同步代码块
为了解决上述的问题的情况,我们可以引入的方法是同步的代码块的操作,把操作共享数据的资源进行加锁的操作
特点
- 锁默认的是打开的关系,有一个线程进去,锁自动关闭
- 里面的代码全部执行完毕,线程出来,锁自动打开。
格式:synchronized(锁){操作共享数据的代码
}
// 改进的代码操作如下所示:
public class MyThread extends Thread{/*表示的是这个类中的所有的对象,都在共享tickets的数据*/static int ticket = 0;/***针对于第一种的创建的方式,可能出现创建多种的线程对象,因此将之加上static 将数据共享 ,如果是对于方法二而言:创建的只有一种Runnable对象。而且是当做参数,创建线程的操作。因此不需要进行共享的声明。*/@Overridepublic void run() {while (true) {//此处是更改之后的数据的操作synchronized ("锁对象要求是唯一"){if (ticket < 100){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}ticket ++ ;System.out.println(getName()+"正在卖"+ticket+"张票");} else {break;}}}}
}改进后的运行的效果是:......
窗口3正在卖95张票
窗口2正在卖96张票
窗口2正在卖97张票
窗口3正在卖98张票
窗口1正在卖99张票
窗口3正在卖100张票
【重点操作】:
在锁结构中,我们能够使用的过程中加上唯一的锁对象,对于锁对象的选择上来说
- 必须保证唯一的特性
- 通常是一个类内会设置一个独立的变量作为锁对象使用
- 包装类不得用于锁对象使用
- 当前类型的Class对象可以作为锁对象,但是不推荐
3.2 同步方法
使用的关键字是synchronized
限制对应的方法是有且只能通过一个线程进入到方法中执行目标的任务
重点进行区分的是有static修饰的方法是静态方法,需要进行考虑的是当前锁对象的情况,以及同步范围的情况。
同步方法的格式:修饰符 synchronized 返回值类型 方法名称(方法参数){}1.同步方法是锁住方法中的所有的代码
2. 锁对象不能够自己指定
// 注意:非静态的同步方法对象是当前调用方法的对象 -> this
public synchronized void sale() {...}// 静态同步方法锁对象是当前类.class 类名.class 唯一的锁对象的特征
public static synchronized void staticSale() {...}
3.2.1 同步方法的范围
非静态的成员方法使用的是 synchronized 同步的约束,同步的范围
重点
:通过当前的实例化对象作为锁对象,实例化对象调用任意 synchronized 修饰的同步方法,所有其他的 synchronized 同步方法,一律不能够进行执行的操作
java中经常使用的是:ArrayList 和 Vector StringBuilder 和 StringBufferHashMap 和 HashTable
静态的成员方法使用 synchronized 同步进行约束的操作,锁对象是 类名.class .无论那一条线程,任何一个对象来执行目标方法,都会被 类名.class 锁住,其他的任意的线程,任意的对象,都无法执行所有其他 static 修饰的 synchronized 约束的同步方法。
例子一:public static synchronized void test1() {for (int i = 0; i < 10; i++) {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Test1 方法");}
}/*
等价于
synchronized (TypeB.class) {for (int i = 0; i < 10; i++) {try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("Test1 方法");}
}*/
例子二:电影院售票的操作套路采用的是通过实现接口的方式来创建线程
public class MyRunnable implements Runnable{
int ticket = 0;/*** 执行的套路是:* 1. 循环* 2. 同步代码块* 3.判断共享数据是否到了末尾,到末尾的情况* 4. 判断共享数据是否到了末尾,没有到末尾的情况*/@Override
public void run() {while (true) {synchronized (MyRunnable.class) {if (ticket == 100){break;} else {ticket ++;System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"张票");}}}
}
}更改成为同步方法的格式为:
public class MyRunnable implements Runnable{int ticket = 0;/*** 执行的套路是:* 1. 循环* 2. 同步代码块* 3.判断共享数据是否到了末尾,到末尾的情况* 4. 判断共享数据是否到了末尾,没有到末尾的情况*/@Overridepublic void run() {while (true) {if (extracted()) break;}}/*** 其中的锁对象是惟一的,其中的对象表示的是this,即为当前的对象** @return*/private synchronized boolean extracted() {if (ticket == 100){return true;} else {ticket ++;System.out.println(Thread.currentThread().getName()+"买了第"+ticket+"张票");}return false;}
}
通过创建接口对象,并且将接口对象作为参数进行传入的操作*/
public class TicketDemo {public static void main(String[] args) {/*** 通过接口的实现,来进行操作,将接口名作为参数,创建线程*/Runnable runnable = new MyRunnable();Thread thread0 = new Thread(runnable);Thread thread1 = new Thread(runnable);Thread thread2 = new Thread(runnable);thread0.setName("窗口1");thread1.setName("窗口2");thread2.setName("窗口3");thread0.start();thread1.start();thread2.start();}
}
3.3 Lock锁
- Lock 实现提供的比 synchronized 方法和语句可以获取更为广泛的锁定操作
- Lock中提供了获的锁和释放锁的方法
- void lock() 获得锁
- void unlock() 释放锁
- lock接口是不能够进行直接的实例化操作的,这里采用的它的实现类ReentrantLock 来实例化 ReentrantLock的构造方法。类ReentrantLock() 创建一个类ReentrantLock的实例。
总结
: 手动上锁,手释放锁。
手动锁的结构是:static Lock mylock = new ReentrantLock();
mylock.lock;try{}finally{mylcok.unlock();// 如果在临界区的代码抛出一个异常,锁必须释放。否则其他的线程将永远阻塞。}
这个结构的优点是确保任何时刻,都只有一个线程进入临界区,一旦一个线程锁定了锁对象,其他的任何线程都无法通过lock语句,当其他的语句调用lock语句的时候,他们会暂停,直到第一个线程释放这个锁对象。
出现的问题:1. 创建三个线程对象,lock对象的创建是在类里面2. 所以出现的是三种不同的锁,所以有可能出现的是没有加锁成功3. 改正的方法可以在前面加上 static 修饰符public class MyThread extends Thread{/*表示的是这个类中的所有的对象,都在共享tickets的数据*/static int ticket = 0;Lock lock = new ReentrantLock();@Overridepublic void run() {while (true) {/*调用获得锁的方法操作,开始上锁*/lock.lock();if (ticket < 100){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}ticket ++ ;System.out.println(getName()+"正在卖"+ticket+"张票");} else {break;}// 关锁的操作lock.unlock();}}
}
public class Demo1 {/***检验多线程的问题** @param args*/public static void main(String[] args) {/** 1. 创建线程对象*/MyThread myThread1 = new MyThread();MyThread myThread2 = new MyThread();MyThread myThread3 = new MyThread();/*通过调用方法起名字*/myThread1.setName("窗口1");myThread2.setName("窗口2");myThread3.setName("窗口3");/*开启线程的操作*/myThread1.start();myThread2.start();myThread3.start();}
}
改进之后的作用:import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;/*** 通过继承的方式操作线程*/
public class MyThread extends Thread{/*表示的是这个类中的所有的对象,都在共享tickets的数据*/static int ticket = 0;static Lock lock = new ReentrantLock();@Overridepublic void run() {while (true) {/*调用获得锁的方法操作,开始上锁*/lock.lock();try {if (ticket < 100){Thread.sleep(100);ticket ++ ;System.out.println(getName()+"正在卖"+ticket+"张票");} else {break;}} catch (InterruptedException e) {e.printStackTrace();} finally {// 关锁的操作lock.unlock();}}}
}
3.4 死锁(错误)
死锁实际上是:指的是两个或者两个以上的进程在执行的过程中,由于竞争资源或者由于彼此的铜线而造成的一种阻塞的现象。若没有外力的作用,它们无法推进下去。
3.4.1 死锁的四个必要的条件
- 互斥条件:在一定的时间某种资源只有一个线程占用。如果此时还有其他的进程请求资源,就只能够等待,直到占有资源的进程用完释放
- 占有且等待条件:指进程已经保持至少一个资源,但是又提出了新的资源的请求,而且该资源已经被其他进程占用,此时请求进程阻塞,但是对于自己已经获得的其他的资源保持不放
- 不可抢占资源:别人已经占有额某项资源,你不能够因为自己也需要该资源,就去把别人的资源抢过来。
- 循环等待的条件:若干个进程之间形成一种头尾相接的循环等待的资源关系。
3.4.2 如何避免死锁
- 避免一个线程同时获得多个锁
- 避免一个线程在锁内同时占用多个资源,尽量保持每个锁只占用一种资源
- 尝试使用定时锁,使用lock.tryLock(timeout)来代替使用内部锁机制
3.5 线程安全
- 临界资源:共享资源(同一个对象),一次只可以有一个线程操作,才能够保证准确性
- 原子操作:不可拆分的步骤,被视为一个整体,其中的步骤不能够被打乱。
3.6 线程不安全
- 完整的步骤可能会被破坏
- 线程内的数据可能会被别的线程修改
举例
public class Printer extends Thread{// 锁需要是同一对象private Object obj = new Object();// 打印机1号public synchronized void print1() {//synchronized (obj){System.out.print(1+" ");System.out.print(2+" ");System.out.print(3+" ");System.out.print(4+" ");System.out.print("\r\n");//}}// 打印机2号public synchronized void print2() {//synchronized (obj) {System.out.print("一 ");System.out.print("二 ");System.out.print("三 ");System.out.print("四 ");System.out.print("\r\n");//}} }
public class Demo1 {public static void main(String[] args) {Printer printer = new Printer( );// 线程1new Thread(() -> {while(true){printer.print1();}}).start();// 线程2new Thread(() -> {while(true){printer.print2();}}).start();} }
相关文章:

线程(一)
线程 1. 线程 定义:线程是进程的组成部分,不同的线程执行不同的任务,不同的功能模块,同时线程使用的资源师由进程管理,主要分配CPU和内存。 在进程中,线程执行的方式是抢占式执行操作,需要考…...

[深入理解SSD系列 闪存实战2.1.8] NAND FLASH Multi Plane Program(写)操作_multi plane 为何能提高闪存速度
前言 上一篇我们介绍了 [深入理解SSD系列 闪存实战2.1.7] NAND FLASH基本编程(写)操作及原理_NAND FLASH Program Operation 源码实现。这只是一次对单个plane 写, 按这样的话, 要先program plane 0 完成后, 再 program plane 1。 如果我偷偷告诉你, 两个 plane 可以一起…...

计算机网络(第八版)——第一章知识总结
本笔记来源于博主上课所记笔记整理,可能不全,欢迎大家批评指正,如果觉得有用记得点个赞,给博主点个关注...该笔记将会持续更新...整理不易,希望大家多多点赞。 第一章 计算机网络体系结构 1.计算机网络的作用 1.1互…...

Linux学习笔记
前段时间看了网课:https://www.bilibili.com/video/BV1mW411i7Qf?spm_id_from333.337.search-card.all.click&vd_source7b9f1ca2783a4c39a4d640a31e23457e 记了一些笔记,先放到这里,后面慢慢整理: 内存分配:分区…...

树与二叉树(概念篇)
树与二叉树1 树的概念1.1 树的简单概念1.2 树的概念名词1.3 树的相关表示2 二叉树的概念2.1 二叉树的简单概念2.1.1 特殊二叉树2.2 二叉树的性质2.3 二叉树的存储结构1 树的概念 1.1 树的简单概念 树是一种非线性的数据结构,它是由n(n>0)个有限节点组成的一个具…...

C++回顾(二十五)—— map/multimap容器
25.1 map/multimap的简介 map是标准的关联式容器,一个map是一个键值对序列,即(key,value)对。它提供基于key的快速检索能力。map中key值是唯一的。集合中的元素按一定的顺序排列。元素插入过程是按排序规则插入,所以不能指定插入位置。map的…...

7.3 向量的数量积与向量积
🙌作者简介:数学与计算机科学学院出身、在职高校高等数学专任教师,分享学习经验、生活、 努力成为像代码一样有逻辑的人! 🌙个人主页:阿芒的主页 ⭐ 高等数学专栏介绍:本专栏系统地梳理高等数学…...

Qt静态扫描(命令行操作)
Qt静态扫描(命令行操作) 前沿: 静态代码分析是指无需运行被测代码,通过词法分析、语法分析、控制流、数据流分析等技术对程序代码进行扫描,找出代码隐藏的错误和缺陷,如参数不匹配,有歧义的嵌…...

【Hadoop】配置文件
Hadoop 配置文件分两类:默认配置文件和自定义配置文件,只有用户想修改某一默认 配置值时,才需要修改自定义配置文件,更改相应属性值 (1)默认配置文件: cd $HADOOP_HOME/share/hadoop common路…...

python进程池
Python进程池是Python标准库中multiprocessing模块提供的一种用于管理进程的方式。它可以使Python程序以并行的方式执行任务,提高程序的运行效率。本篇博客将介绍如何使用Python进程池。 创建进程池 在使用Python进程池之前,我们需要先创建一个进程池对…...

笔记本固态盘数据丢失怎么办?笔记本固态盘怎么恢复数据
如果笔记本固态盘数据丢失怎么办?笔记本固态盘怎么恢复数据?下面将为大家详细地介绍一下笔记本固态硬盘数据恢复的三种实用方法,希望对大家有所帮助。一、简单恢复方法笔记本固态硬盘数据删除以后,较为简单直接的恢复方法就是从回…...

堆的结构与实现
堆的结构与实现二叉树的顺序结构堆的概念及结构堆的实现堆的创建向上调整建堆向下调整建堆堆的操作链接二叉树的顺序结构 堆其实是具有一定规则限制的完全二叉树。 普通的二叉树是不太适合用数组来存储的,因为可能会存在大量的空间浪费。而完全二叉树会更适合使用顺…...

Pandas快速入门
Pandas是Python中非常流行的数据处理库之一,它提供了一种简单而强大的方法来处理和分析数据。在本篇文章中,我将向你介绍Pandas的基础知识,以便你可以开始使用它来处理和分析数据。 安装Pandas 首先,你需要安装Pandas。可以通过…...

LVGL学习笔记18 - 表Table
目录 1. Parts 1.1 LV_PART_MAIN 1.2 LV_PART_ITEMS 2. 样式 2.1 设置行列数 2.2 设置单元格字符串 2.3 设置单元格宽度 2.4 设置表格高度和宽度 2.5 设置字符串颜色 2.6 设置边框颜色 2.7 设置背景颜色 3. 事件 4. CELL CTRL 表格是由包含文本的行、列和单元格构…...

嵌入式安防监控项目——html框架分析和环境信息刷新到网页
目录 一、html控制LED 二、模拟数据上传到html 一、html控制LED 简单来说就是html给boa服务器发了一个控制指令信息,然后boa转发给cgi进程,cgi通过消息队列和主进程通信。主进程再去启动LED子线程。 这是老师给的工程。 以前学32都有这工具那工具来管…...

centos安装docker详细步骤
目录 一.前言 1.环境要求2.官网中文安装参考手册 二.安装步骤 1.卸载旧版本2.安装需要的软件包3.设置docker镜像源 1.配置docker镜像源 方式1:官网地址(外国):方式2:阿里云源:2.查看配置是否成功 4.更新yum软件包索引5.可以查看…...

初识HTML、W3C标准、如何利用IDEA创建HTML项目、HTML基本结构、网页基本信息
一、什么是HTML? HTML——Hyper Text Markup Languagr(超文本标记语言) 超文本包括:文字、图片、音频、视频、动画等 目前网页中常用——HTML5 HTML5提供了一些新的元素和一些有趣的新特性,同时也建立了一些新的规则…...

为什么程序员喜欢这些键盘?
文章目录程序员的爱介绍个人体验程序员的爱 程序员是长时间使用计算机的群体,他们需要一款高品质的键盘来保证舒适的打字体验和提高工作效率。在键盘市场上,有很多不同类型的键盘,但是对于程序员来说,机械键盘是他们最钟爱的选择…...

JS中数组去重的几种方法
JS 中有多种方法可以实现数组去重,下面是几种常用的方法:1、使用 Set 去重:Set 数据结构中不能有重复元素,可以将数组转成 Set 类型,再转回数组。let arr [1,2,3,4,5,6,2,3,4]; let uniqueArr [...new Set(arr)]; co…...

Nginx 配置实例-负载均衡
一、实现效果 浏览器地址栏输入地址 http://192.168.137.129/edu/a.html,负载均衡效果,将请求平均分配到8080和8081两台服务器上。 二、准备工作 1. 准备两台tomcat服务器,一台8080,一台8081 (具体操作如下两个链接) Nginx配置实…...

引出生命周期、生命周期_挂载流程、生命周期_更新流程、生命周期_销毁流程、生命周期_总结——Vue
目录 一、引出生命周期 二、生命周期_挂载流程 三、生命周期_更新流程 四、生命周期_销毁流程 五、生命周期_总结 一、引出生命周期 生命周期: 1.又名:生命周期回调函数、生命周期函数、生命周期钩子。 2.是什么:Vue在关键时刻帮我们调…...

C++ STL学习之【vector的使用】
✨个人主页: Yohifo 🎉所属专栏: C修行之路 🎊每篇一句: 图片来源 The power of imagination makes us infinite. 想象力的力量使我们无限。 文章目录📘前言📘正文1、默认成员函数1.1、默认构造…...

方差分析与单因素方差分析
研究分类型自变量对数值型因变量的影响。检验统计的设定和检验方法与变量间的方差是否相等有关。 例如研究行业、服务等级对投诉数的影响:如表格中给出4个行业、每个行业有3个服务等级、样本容量为7、观测值为投诉数。则构成一个3维的矩阵。 在上述基础上…...

分布式链路追踪组件skywalking介绍
SkyWalking组件概念 一个开源的可观测平台, 用于从服务和云原生基础设施收集, 分析, 聚合及可视化数据。SkyWalking 提供了一种简便的方式来清晰地观测分布式系统, 甚至横跨多个云平台。SkyWalking 更是一个现代化的应用程序性能监控(Application Performance Monitoring)系统…...

SUBMIT的用法
SUBMIT的用法 一、简介 系统MB52/MB51/MB5B等类似的报表 ,虽然数据很全面,执行效率也够快,但是经常会不满足用户需求(增添字段、添加查询条件等),很多ABAP 会选择去COPY出标准程序,然后去做修改…...

网页基本标签、图像标签、链接标签、块内元素和块元素、列表标签、表格标签
一、网页基本标签 标题标签 段落标签 未写段落标签前,文本没有按照想要的格式排列显示 写段落标签后: 每句都是一段,所以句与句距离比较宽 换行标签 同一段,只是把文字换行,所以比较紧凑 水平线标签 字体样式标签 …...

RxJava操作符变换过程
要使用Rxjava首先要导入两个包,其中rxandroid是rxjava在android中的扩展 implementation io.reactivex:rxandroid:1.2.1implementation io.reactivex:rxjava:1.2.0我们在使用rxjava的操作符时都觉得很方便,但是rxjava是怎么实现操作符的转换呢࿰…...

开放平台订单接口
custom-自定义API操作 注册开通 taobao.custom 公共参数 名称 类型 必须 描述 key String 是 调用key(必须以GET方式拼接在URL中) secret String 是 调用密钥 api_name String 是 API接口名称(包括在请求地址中&a…...

CDN相关知识点
1、什么是CDN?CDN的作用是什么? CDN(Content Delivery Network,内容分发网络)是一种通过在多个节点上分布内容以提高网络性能、可靠性和可扩展性的网络解决方案。CDN通过在不同的地理位置部署服务器,使用户…...

【论文阅读】注意力机制与二维 TSP 问题
前置知识 注意力机制 见 这篇 二维 TSP 问题 给定二维平面上 nnn 个点的坐标 S{xi}i1nS\{x_i\}_{i1}^nS{xi}i1n,其中 xi∈[0,1]2x_i\in [0,1]^2xi∈[0,1]2,要找到一个 1∼n1\sim n1∼n 的排列 π\piπ ,使得目标函数 L(π∣s)∥xπ…...