day12 多线程

目录

1.概念相关

1.1什么是线程

1.2什么是多线程

2.创建线程

2.1方式一:继承Thread类

2.1.1实现步骤

2.1.2优缺点

2.1.3注意事项

2.2方式二:实现Runnable接口

2.2.1实现步骤

2.2.2优缺点

2.2.3匿名内部类写法

2.3方式三:实现callable接口

2.3.1callable接口解决了什么问题

2.3.2实现步骤

2.3.3FutureTask的API

2.3.4优缺点

3.线程的常用方法

4.线程安全

4.1什么是线程安全

4.2线程安全问题出现的原因

4.3模拟线程安全问题场景 :取钱

5.线程同步

5.1什么是线程同步

5.2线程同步的核心思想

5.3常见方案

5.4方式一:同步代码块

5.4.1作用:

5.4.2原理:

5.4.3注意事项:

5.4.4锁对象的使用规范 

5.4.5如何实现线程安全的

5.5方式二:同步方法

5.5.1作用

5.5.2原理

5.5.3底层原理

5.5.4同步代码块和同步方法哪种好

5.6lock锁

5.6.1lock锁是什么

5.6.2lock锁的构造器、常用方法

5.6.3锁对象建议加上什么修饰

5.6.4释放锁的操作建议放到哪里

6.线程池

6.1认识线程池

6.2不使用线程池的后果

6.3创建线程池

6.4任务拒绝策略

6.5线程池的注意事项

6.6处理runnable任务

6.4.1ExecutorService的常用方法

6.7处理callable

6.8通过Executors创建线程池

6.8.1方法

6.8.2Executors使用可能存在的陷阱

7.并发、并行

7.1进程

7.2并发的含义

7.3并行的含义


 

1.概念相关

1.1什么是线程

线程(Thread)是一个程序内部的一条执行流程。程序中如果只有一条执行流程,那这个程序就是单线程的程序。

1.2什么是多线程

多线程是指从软硬件上实现的多条执行流程的技术(多条线程由CPU负责调度执行)。

2.创建线程

2.1方式一:继承Thread类

2.1.1实现步骤

【1】定义一个子类MyThread继承线程类java.lang.Thread,重写run()方法

【2】创建MyThread类的对象

【3】调用线程对象的start()方法启动线程(启动后还是执行run方法的)

2.1.2优缺点

【1】优点:编码简单

【2】缺点:线程类已经继承Thread,无法继承其他类,不利于功能的扩展

2.1.3注意事项

【1】启动线程必须是调用start方法,不是调用run方法。

【2】不要把主线程任务放在启动子线程之前。

public class Test {public static void main(String[] args) {Thread t1=new MyThread();t1.start();for (int i = 0; i < 5; i++) {System.out.println("主线程"+i);}}}class MyThread extends Thread{@Overridepublic void run(){for (int i = 0; i < 10; i++){System.out.println("子线程" + i);}}
}

2.2方式二:实现Runnable接口

2.2.1实现步骤

【1】定义一个线程任务类MyRunnable实现Runnable接口,重写run()方法

【2】创建MyRunnable任务对象

【3】把MyRunnable任务对象交给Thread处理

【4】调用线程对象的start()方法启动线程

2.2.2优缺点

【1】优点:任务类只是实现接口,可以继续继承其他类、实现其他接口,扩展性强。

【2】缺点:需要多一个Runnable对象。

2.2.3匿名内部类写法

【1】可以创建Runnable的匿名内部类对象。

【2】再交给Thread线程对象。

【3】再调用线程对象的start()启动线程。

    public static void main(String[] args) {new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 5; i++) {System.out.println("子线程"+i);}}}).start();new Thread(()->{for (int i = 0; i < 5; i++) {System.out.println("子线程2"+i);}}).start();for (int i = 0; i < 5; i++) {System.out.println("主线程"+i);}}

2.3方式三:实现callable接口

2.3.1callable接口解决了什么问题

假如线程执行完毕后有一些数据需要返回,前两种重写的run方法均不能直接返回结果。使用Callable接口和FutureTask类来实现创建,可以返回线程执行完毕后的结果。

2.3.2实现步骤

【1】定义一个类实现Callable接口,重写call方法,封装要做的事情,和要返回的数据。

【2】把Callable类型的对象封装成FutureTask(线程任务对象)。

【3】把线程任务对象交给Thread对象。

【4】调用Thread对象的start方法启动线程。

【5】线程执行完毕后、通过FutureTask对象的的get方法去获取线程任务执行的结果。

2.3.3FutureTask的API

FutureTask提供的构造器说明
public FutureTask<>(Callable call)把Callable对象封装成FutureTask对象。
FutureTask提供的方法说明
public V get() throws Exception获取线程执行call方法返回的结果。

2.3.4优缺点

【1】优点:线程任务类只是实现接口,可以继续继承类和实现接口,扩展性强;可以在线程执行完毕后去获取线程执行的结果。

【2】缺点:编码复杂一点。

public class ThreadDemo3 {public static void main(String[] args) {// 目标:掌握多线程的创建方式三:实现Callable接口,方式三的优势:可以获取线程执行完毕后的结果的。// 3、创建一个Callable接口的实现类对象。Callable<String> c1 = new MyCallable(100);// 4、把Callable对象封装成一个真正的线程任务对象FutureTask对象。/*** 未来任务对象的作用?*    a、本质是一个Runnable线程任务对象,可以交给Thread线程对象处理。*    b、可以获取线程执行完毕后的结果。*/FutureTask<String> f1 = new FutureTask<>(c1); // public FutureTask(Callable<V> callable)// 5、把FutureTask对象作为参数传递给Thread线程对象。Thread t1 = new Thread(f1);// 6、启动线程。t1.start();Callable<String> c2 = new MyCallable(50);FutureTask<String> f2 = new FutureTask<>(c2); // public FutureTask(Callable<V> callable)Thread t2 = new Thread(f2);t2.start();// 获取线程执行完毕后返回的结果try {// 如果主线程发现第一个线程还没有执行完毕,会让出CPU,等第一个线程执行完毕后,才会往下执行!System.out.println(f1.get());} catch (Exception e) {e.printStackTrace();}try {// 如果主线程发现第二个线程还没有执行完毕,会让出CPU,等第一个线程执行完毕后,才会往下执行!System.out.println(f2.get());} catch (Exception e) {e.printStackTrace();}}
}// 1、定义一个实现类实现Callable接口
class MyCallable implements Callable<String> {private int n;public MyCallable(int n) {this.n = n;}// 2、实现call方法,定义线程执行体public String call() throws Exception {int sum = 0;for (int i = 1; i <= n; i++) {sum += i;}return "子线程计算1-" + n + "的和是:"  + sum;}
}

3.线程的常用方法

Tread提供的常用方法说明
public void run()线程的任务方法
public void start()启动线程
public String getName()获取当前线程的名称,线程名称默认是Thread-索引
public void setName(String name)为线程设置名称
public static Thread currentThread()获取当前执行的线程对象
public static void sleep(long time)让当前执行的线程休眠多少毫秒后,再继续执行
public final void join()...让调用当前这个方法的线程先执行完!
public class ThreadApiDemo1 {public static void main(String[] args) {// 目标:搞清楚线程的常用方法。Thread t1 = new MyThread("1号线程");// t1.setName("1号线程");t1.start();System.out.println(t1.getName()); // 线程默认名称是:Thread-索引Thread t2 = new MyThread("2号线程");// t2.setName("2号线程");t2.start();System.out.println(t2.getName()); // 线程默认名称是:Thread-索引// 哪个线程调用这个代码,这个代码就拿到哪个线程Thread m = Thread.currentThread(); // 主线程m.setName("主线程");System.out.println(m.getName()); // main}
}// 1、定义一个子类继承Thread类,成为一个线程类。
class MyThread extends Thread {public MyThread(String name) {super(name); // public Thread(String name)}// 2、重写Thread类的run方法@Overridepublic void run() {// 3、在run方法中编写线程的任务代码(线程要干的活儿)for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() +"子线程输出:" + i);}}
}
public static void main(String[] args) {// 目标:搞清楚Thread类的Sleep方法(线程休眠)for (int i = 1; i <= 10; i++) {System.out.println(i);try {// 让当前执行的线程进入休眠状态,直到时间到了,才会继续执行。// 项目经理让我加上这行代码,如果用户交钱了,我就注释掉。Thread.sleep(1000); // 1000ms = 1s} catch (Exception e) {e.printStackTrace();}}}
public class ThreadApiDemo3 {public static void main(String[] args) {// 目标:搞清楚线程的join方法:线程插队:让调用这个方法线程先执行完毕。MyThread2 t1 = new MyThread2();t1.start();for (int i = 1; i <= 5; i++) {System.out.println(Thread.currentThread().getName() +"线程输出:" + i);if(i == 1){try {t1.join(); // 插队 让t1线程先执行完毕,然后继续执行主线程} catch (Exception e) {e.printStackTrace();}}}}
}class MyThread2 extends Thread {@Overridepublic void run() {for (int i = 1; i <= 5; i++) {System.out.println(Thread.currentThread().getName() +"子线程输出:" + i);}}
}

4.线程安全

4.1什么是线程安全

多个线程,同时操作同一个共享资源的时候,可能会出现业务安全问题。

4.2线程安全问题出现的原因

【1】存在多个线程在同时执行

【2】同时访问一个共享资源

【3】存在修改该共享资源

4.3模拟线程安全问题场景 :取钱

@Data
@AllArgsConstructor
@NoArgsConstructor
public class Account {private String cardId; // 卡号private double money; // 余额// 小明和小红都到这里来了取钱public synchronized void drawMoney(double money) {// 拿到当前谁来取钱。String name = Thread.currentThread().getName();// 判断余额是否足够if (this.money >= money) {// 余额足够,取钱System.out.println(name + "取钱成功,吐出了" + money + "元成功!");// 更新余额this.money -= money;System.out.println(name + "取钱成功,取钱后,余额剩余" + this.money + "元");} else {// 余额不足System.out.println(name + "取钱失败,余额不足");}}
}
// 取钱线程类
public class DrawThread extends Thread{private Account acc; // 记住线程对象要处理的账户对象。public DrawThread(String name, Account acc) {super(name);this.acc = acc;}@Overridepublic void run() {// 小明 小红 取钱acc.drawMoney(100000);}
}
    public static void main(String[] args) {// 目标:模拟线程安全问题。// 1、设计一个账户类:用于创建小明和小红的共同账户对象,存入10万。Account acc = new Account("ICBC-110", 100000);// 2、设计线程类:创建小明和小红两个线程,模拟小明和小红同时去同一个账户取款10万。new DrawThread("小明", acc).start();new DrawThread("小红", acc).start();}

5.线程同步

5.1什么是线程同步

线程同步是线程安全问题的解决方案

5.2线程同步的核心思想

让多个线程先后依次访问共享资源,这样就可以避免出现线程安全问题。

5.3常见方案

加锁:每次只允许一个线程加锁,加锁后才能进入访问,访问完毕后自动解锁,然后其他线程才能再加锁进来。

5.4方式一:同步代码块

5.4.1作用:

把访问共享资源的核心代码给上锁,以此保证线程安全。

5.4.2原理:

每次只允许一个线程加锁后进入,执行完毕后自动解锁,其他线程才可以进来执行

5.4.3注意事项:

对于当前同时执行的线程来说,同步锁必须是同一把(同一个对象),否则会出bug。

5.4.4锁对象的使用规范 

【1】建议使用共享资源作为锁对象,对于实例方法建议使用this作为锁对象。

【2】对于静态方法建议使用字节码(类名.class)对象作为锁对象。

5.4.5如何实现线程安全的

【1】对出现问题的核心代码使用synchronized进行加锁

【2】每次只能一个线程占锁进入访问

// 小明和小红都到这里来了取钱public void drawMoney(double money) {// 拿到当前谁来取钱。String name = Thread.currentThread().getName();// 判断余额是否足够synchronized (this) {if (this.money >= money) {// 余额足够,取钱System.out.println(name + "取钱成功,吐出了" + money + "元成功!");// 更新余额this.money -= money;System.out.println(name + "取钱成功,取钱后,余额剩余" + this.money + "元");} else {// 余额不足System.out.println(name + "取钱失败,余额不足");}}}

5.5方式二:同步方法

5.5.1作用

把访问共享资源的核心方法给上锁,以此保证线程安全。

5.5.2原理

每次只能一个线程进入,执行完毕以后自动解锁,其他线程才可以进来执行

5.5.3底层原理

【1】同步方法其实底层也是有隐式锁对象的,只是锁的范围是整个方法代码。

【2】如果方法是实例方法:同步方法默认用this作为的锁对象。

【3】如果方法是静态方法:同步方法默认用类名.class作为的锁对象。

5.5.4同步代码块和同步方法哪种好

同步代码块锁的范围更小,同步方法锁的范围更大。同步方法可读性更好

    // 小明和小红都到这里来了取钱public synchronized void drawMoney(double money) {// 拿到当前谁来取钱。String name = Thread.currentThread().getName();// 判断余额是否足够if (this.money >= money) {// 余额足够,取钱System.out.println(name + "取钱成功,吐出了" + money + "元成功!");// 更新余额this.money -= money;System.out.println(name + "取钱成功,取钱后,余额剩余" + this.money + "元");} else {// 余额不足System.out.println(name + "取钱失败,余额不足");}}

5.6lock锁

5.6.1lock锁是什么

Lock锁是JDK5开始提供的一个新的锁定操作,通过它可以创建出锁对象进行加锁和解锁,更灵活、更方便、更强大。Lock是接口,不能直接实例化,可以采用它的实现类ReentrantLock来构建Lock锁对象。

5.6.2lock锁的构造器、常用方法

构造器说明
public ReentrantLock​()获得Lock锁的实现类对象
方法名称说明
void lock()获得锁
void unlock()释放锁

5.6.3锁对象建议加上什么修饰

建议使用final修饰,防止被别人篡改

5.6.4释放锁的操作建议放到哪里

建议将释放锁的操作放到finally代码块中,确保锁用完了一定会被释放

    private final Lock lk = new ReentrantLock(); // 保护锁对象// 小明和小红都到这里来了取钱public void drawMoney(double money) {// 拿到当前谁来取钱。String name = Thread.currentThread().getName();lk.lock(); // 上锁try {// 判断余额是否足够if (this.money >= money) {// 余额足够,取钱System.out.println(name + "取钱成功,吐出了" + money + "元成功!");// 更新余额this.money -= money;System.out.println(name + "取钱成功,取钱后,余额剩余" + this.money + "元");} else {// 余额不足System.out.println(name + "取钱失败,余额不足");}} finally {lk.unlock();// 解锁}}

6.线程池

6.1认识线程池

线程池就是一个可以复用线程的技术。

6.2不使用线程池的后果

用户每发起一个请求,后台就需要创建一个新线程来处理,下次新任务来了肯定又要创建新线程处理的,  创建新线程的开销是很大的,并且请求过多时,肯定会产生大量的线程出来,这样会严重影响系统的性能。

6.3创建线程池

通过ThreadPoolExecutor创建线程池。使用ExecutorService的实现类ThreadPoolExecutor自创建一个线程池对象。

【1】参数一:corePoolSize : 指定线程池的核心线程的数量。

【2】参数二:maximumPoolSize:指定线程池的最大线程数量。

【3】参数三:keepAliveTime :指定临时线程的存活时间。

【4】参数四:unit:指定临时线程存活的时间单位(秒、分、时、天)

【5】参数五:workQueue:指定线程池的任务队列。

【6】参数六:threadFactory:指定线程池的线程工厂。

【7】参数七:handler:指定线程池的任务拒绝策略(线程都在忙,任务队列也满了的时候,新任务来了该怎么处理)

6.4任务拒绝策略

策略说明
ThreadPoolExecutor.AbortPolicy()丢弃任务并抛出RejectedExecutionException异常。是默认的策略
ThreadPoolExecutor. DiscardPolicy()丢弃任务,但是不抛出异常,这是不推荐的做法
ThreadPoolExecutor. DiscardOldestPolicy()抛弃队列中等待最久的任务 然后把当前任务加入队列中
ThreadPoolExecutor. CallerRunsPolicy()由主线程负责调用任务的run()方法从而绕过线程池直接执行

6.5线程池的注意事项

// 1、定义一个线程任务类实现Runnable接口
public class MyRunnable implements Runnable {// 2、重写run方法,设置线程任务@Overridepublic void run() {for (int i = 0; i < 5; i++) {System.out.println(Thread.currentThread().getName() + "输出:" + i);try {Thread.sleep(Integer.MAX_VALUE);} catch (Exception e) {e.printStackTrace();}}}
}
    public static void main(String[] args) {// 目标:创建线程池对象来使用。// 1、使用线程池的实现类ThreadPoolExecutor声明七个参数来创建线程池对象。ExecutorService pool = new ThreadPoolExecutor(3, 5,10, TimeUnit.SECONDS, new ArrayBlockingQueue<>(3),Executors.defaultThreadFactory(), new ThreadPoolExecutor.CallerRunsPolicy());// 2、使用线程池处理任务!看会不会复用线程?Runnable target = new MyRunnable();pool.execute(target); // 提交第1个任务 创建第1个线程 自动启动线程处理这个任务pool.execute(target); // 提交第2个任务 创建第2个线程 自动启动线程处理这个任务pool.execute(target); // 提交第2个任务 创建第3个线程 自动启动线程处理这个任务pool.execute(target);pool.execute(target);pool.execute(target);pool.execute(target); // 到了临时线程的创建时机了pool.execute(target); // 到了临时线程的创建时机了pool.execute(target); // 到了任务拒绝策略了,忙不过来// 3、关闭线程池 :一般不关闭线程池。// pool.shutdown(); // 等所有任务执行完毕后再关闭线程池!
//        pool.shutdownNow(); // 立即关闭,不管任务是否执行完毕!}

6.6处理runnable任务

6.4.1ExecutorService的常用方法

方法名称说明
void execute(Runnable command)执行 Runnable 任务
Future<T> submit(Callable<T> task)执行 Callable 任务,返回未来任务对象,用于获取线程返回的结果
void shutdown()等全部任务执行完毕后,再关闭线程池!
List<Runnable> shutdownNow()立刻关闭线程池,停止正在执行的任务,并返回队列中未执行的任务
        // 2、使用线程池处理任务!看会不会复用线程?Runnable target = new MyRunnable();pool.execute(target); // 提交第1个任务 创建第1个线程 自动启动线程处理这个任务pool.execute(target); // 提交第2个任务 创建第2个线程 自动启动线程处理这个任务pool.execute(target); // 提交第2个任务 创建第3个线程 自动启动线程处理这个任务pool.execute(target);pool.execute(target);pool.execute(target);pool.execute(target); // 到了临时线程的创建时机了pool.execute(target); // 到了临时线程的创建时机了pool.execute(target); // 到了任务拒绝策略了,忙不过来// 3、关闭线程池 :一般不关闭线程池。pool.shutdown(); // 等所有任务执行完毕后再关闭线程池!pool.shutdownNow(); // 立即关闭,不管任务是否执行完毕!

6.7处理callable

线程池如何处理Callable任务,并得到任务执行完后返回的结果?

Future<T> submit(Callable<T> command)

6.8通过Executors创建线程池

6.8.1方法

是一个线程池的工具类,提供了很多静态方法用于返回不同特点的线程池对象。这些方法的底层,都是通过线程池的实现类ThreadPoolExecutor创建的线程池对象

方法名称说明
public static ExecutorService newFixedThreadPool​(int nThreads)创建固定线程数量的线程池,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程替代它。
public static ExecutorService newSingleThreadExecutor()创建只有一个线程的线程池对象,如果该线程出现异常而结束,那么线程池会补充一个新线程。
public static ExecutorService newCachedThreadPool()线程数量随着任务增加而增加,如果线程任务执行完毕且空闲了60s则会被回收掉。
public static ScheduledExecutorService newScheduledThreadPool​(int corePoolSize)创建一个线程池,可以实现在给定的延迟后运行任务,或者定期执行任务。

6.8.2Executors使用可能存在的陷阱

【1】大型并发系统环境中使用Executors如果不注意可能会出现系统风险。

【2】不适合做大型互联网场景的线程池方案

【3】建议使用ThreadPoolExecutor来指定线程池参数,这样可以明确线程池的运行规则,规避资源耗尽的风险。

7.并发、并行

7.1进程

【1】正在运行的程序(软件)就是一个独立的进程。

【2】线程是属于进程的,一个进程中可以同时运行很多个线程。

【3】进程中的多个线程其实是并发和并行执行的。

7.2并发的含义

进程中的线程是由CPU负责调度执行的,但CPU能同时处理线程的数量有限,为了保证全部线程都能往前执行,CPU会轮询为系统的每个线程服务,由于CPU切换的速度很快,给我们的感觉这些线程在同时执行,这就是并发。

7.3并行的含义

在同一个时刻上,同时有多个线程在被CPU调度执行。

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

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

相关文章

Cesium 相机控制器(1)-wheel 实现原理简析

Cesium 相机控制器(1)-wheel 实现原理简析 已经做大量简化, 不是代码最终的样子. Viewer┖ CesiumWidget┖ ScreenSpaceCameraController(_screenSpaceCameraController)┣ CameraEventAggregator(_aggregator) // 相机事件代理┃ ┖ ScreenSpaceEventHandler(_eventHandler…

Notion爆红背后,笔记成了AI创业新共识?

在数字化时代&#xff0c;笔记软件已成为我们记录、整理和创造知识的得力助手。本文将带您深入了解Notion以及其他五个AI笔记产品&#xff0c;它们如何通过AI重塑笔记体验&#xff0c;满足我们快速记录、捕捉灵感、智能整理、情感陪伴和自动撰写文章的五大核心需求。 ———— …

golang国内proxy设置

go env -w GOPROXYhttps://goproxy.cn,direct经常使用的两个, goproxy.cn 和 goproxy.io 连接分别是 https://goproxy.cn https://goproxy.io 如果遇到某些包下载不下来的情况&#xff0c;可尝试更换数据源 更推荐使用https://goproxy.cn 速度快&#xff0c;缓存的包多 提醒…

如何建立与众不同的市场洞察能力【深度】

来源&#xff1a;战略研发领航 建立与众不同的市场洞察机制&#xff0c;展示了如何在组织中建立一种以数据和洞察为核心的文化&#xff0c;并通过4S周期&#xff08;架构、探查、塑造、成型&#xff09;的洞察工作方法论&#xff0c;指导领导者和团队在各个层级上进行更有效的思…

Upload-labs靶场Pass01-Pass21全解

文章目录 Pass-01 前端JSJS绕过上传或者用burp抓包的方式 Pass-02 MIME检测Pass-03 特殊文件后缀黑白名单绕过特殊文件名绕过 Pass-04 .htacess上传Pass-05 user.ini文件上传Pass-06 大小写绕过Pass-07 空格绕过Pass-08 .绕过Pass-09 ::$DATA绕过Pass-10 .空格.绕过Pass-11 双写…

深度体验:IntelliJ Idea自带AI Assistant,开启面向AI编程新纪元!

首发公众号&#xff1a; 赵侠客 引言 JetBrains AI Assistant 是 JetBrains 集成开发环境&#xff08;IDE&#xff09;中嵌入的一款智能开发助手工具&#xff0c;旨在通过人工智能技术来简化和提升软件开发过程&#xff0c;我深度体验了一下在IntelliJ IDEA 2024.2 Beta (Ulti…

hive 中编写生成连续月sql

记录一下 sql 编写生成从一个确定的起始月份到当前月份的连续月份序列 SELECT substr(add_months(table1.start_dt,table2.pos),1,4) AS INDICT_YEAR,substr(add_months(table1.start_dt,table2.pos),1,7) AS INDICT_MON FROM (SELECT 2024-01-01 AS start_dt,substr(CURRE…

CVPR24《Neural Markov Random Field for Stereo Matching》

论文地址&#xff1a; https://arxiv.org/abs/2403.11193 源码地址&#xff1a; https://github.com/aeolusguan/NMRF 概述 手工设计的MRF模型在传统的立体匹配中占据主导地位&#xff0c;但与端到端的深度学习模型相比&#xff0c;其建模准确性不足。尽管深度学习大大改进了MR…

GraphSAGE (SAmple and aggreGatE)知识总结

1.前置知识 inductive和transductive 模型训练&#xff1a; Transductive learning在训练过程中已经用到测试集数据&#xff08;不带标签&#xff09;中的信息&#xff0c;而Inductive learning仅仅只用到训练集中数据的信息。 模型预测&#xff1a; Transductive learning只能…

作业练习1

要求&#xff1a;R1-R2-R3-R4-R5 RIP 100 运行版本2 R6-R7 RIP 200 运行版本1 1.使用合理IP地址规划网络&#xff0c;各自创建环回接口 2.R1创建环回 172.16.1.1/24 172.16.2.1/24 172.16.3.1/24 3.要求R3使用R2访问R1环回 4.减少路由条目数量&#xff0c;R1-R2之间增加路由传递…

C++进阶之C++11

个人主页&#xff1a;点我进入主页 专栏分类&#xff1a;C语言初阶 C语言进阶 数据结构初阶 Linux C初阶 算法 C进阶 欢迎大家点赞&#xff0c;评论&#xff0c;收藏。 一起努力&#xff0c;一起奔赴大厂 目录 一.列表初始化 1.1一切皆可用列表初始化 1.2init…

U盘数据丢失?一招教你如何使用四种技巧轻松找回!

每一个打工人可能都是被各种文件所困扰的&#xff0c;而且现在不仅仅是工作上&#xff0c;还有学习以及日常的生活记录也需要接触到各类的数据&#xff0c;拿我们平时用软件时产生的文件、图片、视频等等来说&#xff0c;就占据了磁盘的大部分空间&#xff0c;当然有时候也会选…

CTFHub——XSS——反射型

1、反射型&#xff1a; 发现为表单式&#xff0c;猜测哪个可能存在注入漏洞&#xff0c;分别做测试注入发现name框存在xss漏洞 输入发现有回显但不是对方cookie&#xff0c;参考wp发现要用xss线上平台 将xss平台测试语句注入&#xff0c;将得到的url编码地址填入url框&#xf…

《学会 SpringMVC 系列 · 写入拦截器 ResponseBodyAdvice》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…

MATLAB画散点密度图(附代码和测试数据的压缩包)

1. 有关 Matlab 获取代码关注WZZHHH回复关键词&#xff0c;或者咸鱼关注&#xff1a;WZZHHH123 怀俄明探空站数据解算PWV和Tm&#xff1a;怀俄明探空站数据解算PWV和Tm 怀俄明多线程下载探空站数据&#xff08;包括检查和下载遗漏数据的代码&#xff09;&#xff1a;怀俄明多线…

VMware安装Win10系统(保姆级教程)

需要自己先下载并安装VMware 和Win10系统镜像&#xff1a; VMware官网&#xff1a;VMware - Delivering a Digital Foundation For Businesses Win10下载地址&#xff1a;MSDN,我告诉你 1.新建虚拟机设置 2.启动Win10虚拟机设置 注意&#xff1a; 当出现有字体的时候&#…

一款绿色免费免安装的hosts文件编辑器

BlueLife Hosts Editor 是一款免费的 Hosts 文件编辑工具&#xff0c;主要用于管理和修改电脑系统的 Hosts 文件。该软件具有多种功能&#xff0c;包括添加、删除和更新域名记录&#xff0c;以及调整 IP 与网域名称的交叉对应关系&#xff0c;类似于 DNS 的功能。 该软件特别适…

filebeat

1、作用 1、可以在本机收集日志2、也可以远程收集日志3、轻量级的日志收集系统&#xff0c;可以在非java环境运行。logstash是在jmv环境中运行&#xff0c;资源消耗很大&#xff0c;启动一个logstash要消耗500M左右的内存&#xff0c;filebeat只消耗10M左右的内存。收集nginx的…

Qt 学习第四天:信号和槽机制(核心特征)

信号和槽的简介 信号和插槽用于对象之间的通信。信号和插槽机制是Qt的核心特征&#xff0c;可能是不同的部分大部分来自其他框架提供的特性。信号和槽是由Qt的元对象系统实现的。介绍&#xff08;来自Qt帮助文档Signals & Slots&#xff09; 在GUI编程中&#xff0c;当我们…

使用 Rough.js 创建动态可视化网络图

本文由ScriptEcho平台提供技术支持 项目地址&#xff1a;传送门 使用 Rough.js 创建动态可视化网络图 应用场景 Rough.js 是一个 JavaScript 库&#xff0c;它允许开发人员使用毛边风格创建可视化效果。该库适用于各种应用程序&#xff0c;例如&#xff1a; 数据可视化地图…