JavaWeb6-线程常用方法

news2024/9/22 17:17:04

目录

1.线程等待join(共有3个方法重载)

1.1.public void join()

1.2.public void join(long millis)

2.线程终止

2.1.通过自定义标记符来中断(常用)

2.2.调用 interrupt() 方法来中断(常用,最推荐使用)

2.2.1.Thread.interrupted()

2.2.2.Thread.currentThread().isInterrupted()

--->PS:(常见面试题)interrupted VS isInterrupted

2.3.使用stop停止线程(过期方法,不推荐使用)

3.yield让出CPU的执行权

4.获取当前线程

5.休眠当前线程

5.1.使用sleep休眠

5.2.使用TimeUnit休眠

PS:(线程练习题1)在主线程中创建两个子线程,每个子线程中产生一个随机数,最终等待子线程执行完之后,在主线程中累加两个子线程的结果

PS:(线程练习题2)实现多线程数组求和


1.线程等待join(共有3个方法重载)

有时我们需要等待⼀个线程完成它的⼯作后,才能进⾏⾃⼰的下⼀步⼯作。这时就需要⼀个⽅法明确等待线程的结束。

相比isAlive()的优势:①写法更优雅;②使用wait()进行阻塞等待,会使用更小的资源来完成等待的工作。

1.1.public void join()

/**
 * 关于join示例
 */
public class ThreadByJoin {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            //1.张三开始上班
            System.out.println("1.张三开始上班");
            //2.张三正在上班
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //3.张三下班
            System.out.println("3.张三下班");
        });
        t1.start();

        //等待线程t1执行完之后,再执行后面的代码
        t1.join();

        Thread t2 = new Thread(() -> {
            //1.李四开始上班
            System.out.println("1.李四开始上班");
            //2.李四正在上班
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            //3.李四下班
            System.out.println("3.李四下班");
        });
        t2.start();
    }
}

 

查看源码:

 

1.2.public void join(long millis)

import java.time.LocalDateTime;

public class ThreadByJoin {
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            System.out.println("1.张三开始上班" + LocalDateTime.now());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("3.张三下班" + LocalDateTime.now());
        });
        t1.start();

        t1.join(500);

        Thread t2 = new Thread(() -> {
            System.out.println("1.李四开始上班" + LocalDateTime.now());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("3.李四下班" + LocalDateTime.now());
        });
        t2.start();
    }
}

查看源码:

2.线程终止

李四⼀旦进到⼯作状态,就会按照⾏动指南上的步骤去进⾏⼯作,不完成是不会结束的。但有时需要增加⼀些机制,例如⽼板突然来电话了,说转账的对⽅是个骗⼦,需要赶紧停⽌转账,那张三该如何通知李四停⽌呢?这就涉及到我们的停⽌线程的⽅式了。

2.1.通过自定义标记符来中断(常用)

/**
 * 使用自定义标识符终止线程
 */
public class ThreadInterrupt {
    //1.声明一个自定义标识符(一定要加volatile(易挥发的,不稳定的)关键字)
    private volatile static boolean flag = false;

    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while(!flag) {
                System.out.println("正在转账......");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println("啊?差点误了大事!");
        });
        thread.start();

        Thread.sleep(3000);

        //终止线程
        System.out.println("有内鬼,终止交易!");
        flag = true;
    }
}

但其问题在于:线程中断地不够及时。因为线程在执行过程中,无法调用 while(!isInterrupt) 来判断线程是否为终止状态,它只能在下一轮运行时判断是否要终止当前线程。

class InterruptFlag {
    // 自定义的中断标识符
    private static volatile boolean isInterrupt = false;

    public static void main(String[] args) throws InterruptedException {
        // 创建可中断的线程实例
        Thread thread = new Thread(() -> {
            while (!isInterrupt) { // 如果 isInterrupt=true 则停止线程
                System.out.println("thread 执行步骤1:线程即将进入休眠状态");
                try {
                    // 休眠 1s
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("thread 执行步骤2:线程执行了任务");
            }
        });
        thread.start(); // 启动线程

        // 休眠 100ms,等待 thread 线程运行起来
        Thread.sleep(100);
        System.out.println("主线程:试图终止线程 thread");
        // 修改中断标识符,中断线程
        isInterrupt = true;
    }
}

期望的是:线程执行了步骤 1 之后,收到中断线程的指令,然后就不要再执行步骤 2 了,但上述执行结果看出,使用自定义中断标识符无法实现预期结果。

2.2.调用 interrupt() 方法来中断(常用,最推荐使用)

使用 interrupt 方法可以给执行任务的线程,发送一个中断线程的指令,它并不直接中断线程,而是发送一个中断线程的信号,把是否正在中断线程的主动权交给代码编写者。相比于自定义中断标识符,它能更及时的接收到中断指令。

public static void main(String[] args) throws InterruptedException {
    // 创建可中断的线程实例
    Thread thread = new Thread(() -> {
        while (!Thread.currentThread().isInterrupted()) {
            System.out.println("thread 执行步骤1:线程即将进入休眠状态");
            try {
                // 休眠 1s
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                System.out.println("thread 线程接收到中断指令,执行中断操作");
                // 中断当前线程的任务执行
                break;
            }
            System.out.println("thread 执行步骤2:线程执行了任务");
        }
    });
    thread.start(); // 启动线程

    // 休眠 100ms,等待 thread 线程运行起来
    Thread.sleep(100);
    System.out.println("主线程:试图终止线程 thread");
    // 修改中断标识符,中断线程
    thread.interrupt();
}

从执行结果看出,线程在接收到中断指令之后,立即中断了线程。

interrupt()(执行终止)需要配合 Thread.interrupted()(判断终止)或 Thread.currentThread().isInterrupted()(判断终止)来使用。

使⽤ Thread.interrupted() 或者 Thread.currentThread().isInterrupted() 代替⾃定义标志位。

Thread内部包含了一个boolean类型的变量作为线程是否被中断的标记。

2.2.1.Thread.interrupted()

/**
 * 使用interrupt终止线程
 */
public class ThreadInterrupt2 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while(!Thread.interrupted()) { //Thread.interrupted()判断线程是否被终止,如果线程被终止,返回true;否则返回false。
                System.out.println("正在转账......");
            }
            System.out.println("啊?险些误了大事!");
        });
        //启动线程
        thread.start();

        Thread.sleep(100);

        //终止线程
        thread.interrupt();
        System.out.println("有内鬼,终止交易!");
    }
}

2.2.2.Thread.currentThread().isInterrupted()

public class ThreadInterrupt2 {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            while(!Thread.currentThread().isInterrupted()) { //得到当前的线程,判断其是否是终止状态,如果是终止状态,返回true,否则返回false。 
                System.out.println("正在转账......");
            }
            System.out.println("啊?险些误了大事!");
        });
        thread.start();

        Thread.sleep(100);
        
        thread.interrupt();
        System.out.println("有内鬼,终止交易!");
    }
}

--->PS:(常见面试题)interrupted VS isInterrupted

二者执行结果一样。区别如下:

①interrupted属于静态方法,所有程序都可以直接调用的全局方法;而isInterrupted属于某个实例的私有方法。

②interrupted在使用完之后会重置中断标识符为初始状态false;而isInterrupted在使用完之后不会重置中断标识符。

推荐使用isInterrupted,不建议用interrupted是因为它是全局的,用完后状态会自动回滚,加剧了程序的复杂性和理解上的难度。

public class ThreadInterrupt2 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (!Thread.currentThread().isInterrupted()) { }
                System.out.println("isInterrupted:" + Thread.currentThread().isInterrupted());
                System.out.println("isInterrupted:" + Thread.currentThread().isInterrupted());
                System.out.println("isInterrupted:" + Thread.currentThread().isInterrupted());
                System.out.println();
                System.out.println("interrupted:" + Thread.interrupted());
                System.out.println("interrupted:" + Thread.interrupted());
                System.out.println("interrupted:" + Thread.interrupted());
            }
        });
        t.start();
        Thread.sleep(100);
        t.interrupt();
    }
}

标识符默认为false,表示线程未被终止。

public class ThreadInterrupt2 {
    public static void main(String[] args) throws InterruptedException {
        Thread t = new Thread(new Runnable() {
            @Override
            public void run() {
                while (!Thread.interrupted()) { }
                System.out.println("isInterrupted:" + Thread.currentThread().isInterrupted());
                System.out.println("isInterrupted:" + Thread.currentThread().isInterrupted());
                System.out.println("isInterrupted:" + Thread.currentThread().isInterrupted());
                System.out.println();
                System.out.println("interrupted:" + Thread.interrupted());
                System.out.println("interrupted:" + Thread.interrupted());
                System.out.println("interrupted:" + Thread.interrupted());
            }
        });
        t.start();
        Thread.sleep(100);
        t.interrupt();
    }
}

2.3.使用stop停止线程(过期方法,不推荐使用)

stop 方法是被 @Deprecated 修饰的过期方法,并且在其源码注释的第一句话就说明了 stop 方法为非安全的方法:因为 stop 方法会直接停止线程,这样就没有给线程足够的时间来处理停止前的保存工作,就会造成数据不完整的问题。在最新版本 Java 中,此方法已经被直接移除了,所以强烈不建议使用。

小结——停止线程的 3 种方法:

  1. 自定义中断标识符,此方法的缺点是不能及时响应中断请求;
  2. 使用 interrupt,此方法是发送一个中断信号给线程,它可以及时响应中断,也是最推荐使用的方法;
  3. stop 方法,过期的不推荐使用。

3.yield让出CPU的执行权

  • static静态方法。
  • native表示yield是原生的方法,是JVM里的一个方法,调用C/C++里的yield方法,不是Java的方法。

yield不改变线程的状态,但是会重新去排队,而排队之后选择谁是不确定的。

yield方法会让出CPU执行权,让线程调度器重新随机调度线程,是有一定几率再一次调度到出让CPU执行权的线程上,这一次它就会接着刚才的继续往后执行到线程的方法了,不会再让一次执行权,因为yield已经被执行过。

/**
 * yield方法演示(让出CPU的执行权)
 */
public class ThreadYield {
    public static void main(String[] args) {
        Thread t1 = new Thread(() -> {
            //得到当前线程
            Thread cThread = Thread.currentThread();
            for (int i = 0; i < 10; i++) {
                //让出CPU执行权
                Thread.yield();
                System.out.println("执行线程:" + cThread.getName());
            }
        }, "张三");
        t1.start();

        //创建并启动线程
        new Thread(() -> {
            //在一个main方法中可以起2个相同的cThread线程名字,是因为()->{}相当于有2个匿名内部类,都是在自己的作用域里,两个变量cThread是互相看不到的,彼此是隔离的
            Thread cThread = Thread.currentThread();
            for (int i = 0; i < 10; i++) {
                System.out.println("执行线程:" + cThread.getName());
            }
        },"李四").start();
    }
}

4.获取当前线程

public class ThreadDemo { 
    public static void main(String[] args) {
        Thread thread = Thread.currentThread();
        System.out.println(thread.getName());
    }
}

5.休眠当前线程

5.1.使用sleep休眠

public class ThreadSleep {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(() -> {
            try {
                Thread.sleep(60 * 60 * 1000);
            } catch (InterruptedException e) {
                System.out.println("我接受到了终止执行的通知");
//                e.printStackTrace();
            }
        });
        thread.start();
        Thread.sleep(1000);
        System.out.println("终止子线程thread");
        thread.interrupt();
    }
}

缺点:在休眠较长时间时,还需要自己手动计算时间,麻烦、易错。

5.2.使用TimeUnit休眠

import java.util.concurrent.TimeUnit;

TimeUnit.DAYS.sleep(1);//天(实际用的少)
TimeUnit.HOURS.sleep(1);//⼩时
TimeUnit.MINUTES.sleep(1);//分
TimeUnit.SECONDS.sleep(1);//秒
TimeUnit.MILLISECONDS.sleep(1000);//毫秒
TimeUnit.MICROSECONDS.sleep(1000);//微妙
TimeUnit.NANOSECONDS.sleep(1000);//纳秒

查看源码(实现原理-套了个壳):

PS:(线程练习题1)在主线程中创建两个子线程,每个子线程中产生一个随机数,最终等待子线程执行完之后,在主线程中累加两个子线程的结果

实现思路①:使用主线程把两个普通子线程(无返回值)生成的随机数值保存起来,等两个子线程执行完之后进行累加操作。考察如何把线程内部的变量赋值给全局变量。

JVM规定:在一个线程中修改另一个线程中的私有变量是不安全的。

在一个线程中可以打印另一个线程中的属性,但不能修改。

解决方案:将num1和num2提成公共的全局变量:加static关键字并将其放在类中main方法外。

import java.util.Random;

/**
 * 在主线程中创建两个子线程,每个子线程中产生一个随机数,最终等待子线程执行完之后,在主线程累计两个子线程的结果
 */
public class ThreadDemo14 {
    static int num1 = 0;
    static int num2 = 0;
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(() -> {
            num1 = new Random().nextInt(10);
        });
        t1.start();

        Thread t2 = new Thread(() -> {
            num2 = new Random().nextInt(10);
        });
        t2.start();

        t1.join();
        t2.join();
        System.out.println("最终的结果:" + (num1 + num2));
    }
}

实现思路②:两个子线程使用有返回值的线程调用,执行完将生成的随机数值返回给主线程,主线程把值进行累加。

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

public class ThreadDemo15 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        FutureTask<Integer> futureTask = new FutureTask<>(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int num = new Random().nextInt(10);
                return num;
            }
        });

        Thread t1 = new Thread(futureTask);
        Thread t2 = new Thread(futureTask);
        t1.start();
        t2.start();

        int num1 = futureTask.get();
        int num2 = futureTask.get();
        System.out.println("最终的结果:" + (num1 + num2));
    }
}

注:

  • 普通线程(无返回值)在打印最终结果前一定要加join()等待线程执行完;
  • 而带返回值的线程有get(),get方法需要得到线程的返回值,当线程执行完才能有返回值,所以不用加join()。

PS:(线程练习题2)实现多线程数组求和

  1. 给定一个很长的数组 (长度 1000w), 通过随机数的方式生成 1-100 之间的整数.
  2. 实现代码, 能够创建两个线程, 对这个数组的所有元素求和.
  3. 其中线程1 计算偶数下标元素的和, 线程2 计算奇数下标元素的和.
  4. 最终再汇总两个和, 进行相加.
  5. 记录程序的执行时间.
实现思路有2种(同上),此处使用思路2:

import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

/**
 * 实现多线程大数组相加
 */
public class ThreadDemo16 {
    public static void main(String[] args) throws ExecutionException, InterruptedException {
        //记录开始执行时间
        long stime = System.currentTimeMillis(); //返回的是一个13位的时间戳-毫秒数

        int[] arrs = new int[10000000];

        //1.使用随机数初始化数组
        Random random = new Random();
        for (int i = 0; i < arrs.length; i++) {
            arrs[i] = (random.nextInt(100) + 1);
        }

        //2.创建两个线程执行相加操作
        //2.1.返回偶数之和
        FutureTask<Integer> task1 = new FutureTask<Integer>(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int temp = 0;
                for (int i = 0; i < arrs.length; i = i + 2) {
                    temp += arrs[i];
                }
                System.out.println("线程1:" + temp);
                return temp;
            }
        });
        Thread t1 = new Thread(task1);
        t1.start();

        //2.2.返回奇数之和
        FutureTask<Integer> task2 = new FutureTask<Integer>(new Callable<Integer>() {
            @Override
            public Integer call() throws Exception {
                int temp = 0;
                for (int i = 1; i < arrs.length; i = i + 2) {
                    temp += arrs[i];
                }
                System.out.println("线程2:" + temp);
                return temp;
            }
        });
        Thread t2 = new Thread(task2);
        t2.start();

        int sum = task1.get() + task2.get();
        System.out.println("最终结果:" + sum);

        //记录执行完成时间
        long etime = System.currentTimeMillis(); //返回的是一个13位的时间戳

        //程序执行时间 = 执行完成时间 - 开始执行时间
        System.out.println("程序执行时间:" + (etime - stime) + "ms");
    }
}

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

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

相关文章

Ubuntu安装落雪音乐LX Music

网址&#xff1a; https://lxmusic.toside.cn/ 以 .deb 结尾的文件为在 Linux 系统上运行的版本&#xff0c;软件还有 .rpm/AppImage/pacman 格式的 Linux 包&#xff0c;但没有上传到网盘&#xff0c;可自行到项目发布页面下载。 在Ubuntu上安装比较简单。 安装成功 打开音乐…

maven多环境配置

maven多环境配置 参考网址: https://mp.weixin.qq.com/s/-e74bd2wW_RLx7i4YF5M2w https://mp.weixin.qq.com/s/3p53kBHqys58QdMme6lR4A 项目地址 https://gitee.com/shao_ming314/maven-profile-dir 项目说明 该项目基于目录进行多环境配置 , 具体的配置文件在 src/resource…

【Opencv--自适应图像二值化】cv2.adaptiveThreshold()

【Opencv–adaptiveThreshold】自适应阈值图像二值化 文章目录【Opencv--adaptiveThreshold】自适应阈值图像二值化1. 介绍2. adaptiveThreshold函数2.1 函数调用2.2 补充说明3. 代码示例4. 效果4.1 原图&#xff08;ori.img&#xff09;4.2 处理后5. 参考1. 介绍 在这里 cv2.…

ArcGIS Enterprise on Kubernetes 11.0安装示例

博客主页&#xff1a;https://tomcat.blog.csdn.net 博主昵称&#xff1a;农民工老王 主要领域&#xff1a;Java、Linux、K8S 期待大家的关注&#x1f496;点赞&#x1f44d;收藏⭐留言&#x1f4ac; 目录安装前置条件基本安装解压文件生成秘钥执行安装脚本配置DNS方法一方法二…

快速上手:Prometheus和Grafana入门教程

目录一、简介二、安装Prometheus2.1 二进制安装2.2 添加到system服务2.3 访问UI三、安装Granfa3.1 Docker部署Mysql3.2 Docker部署Grafana3.3 访问UI3.4 添加Prometheus为数据源四、安装Exporter收集数据4.1 node_exporter 服务器监控下载解压启动node_exporter服务与整合Prome…

聚类-理论补充2

目录 一。拉普拉斯矩阵的定义 二。谱聚类算法&#xff1a;未正则拉普拉斯矩阵 三。谱聚类算法&#xff1a;随机游走拉普拉斯矩阵 四。谱聚类算法&#xff1a;对称拉普拉斯矩阵 五。进一步思考 六。随机游走和拉普拉斯矩阵的关系 七。标签传递算法 一。拉普拉斯矩阵的定义 …

MySQL(六)

查询优化 在编写快速的查询之前&#xff0c;需要清楚一点&#xff0c;真正重要的是响应时间&#xff0c;而且要知道在整个SQL语句的执行过程中每个步骤都花费了多长时间&#xff0c;要知道哪些步骤是拖垮执行效率的关键步骤&#xff0c;想要做到这点&#xff0c;必须要知道查询…

Qt之调色板类QPalette的使用

文章目录QPalette调色板类前言代码知识点讲解QPalette调色板类 前言 Qt提供的调色板类QPalette专门用于管理部件的外观显示&#xff0c;相当于部件或对话框的调色板&#xff0c;管理他们所有的颜色信息。每个部件都包含一个QPalette对象&#xff0c;在显示时&#xff0c;按照…

OnGUI Color 控件||Unity 3D GUI 简介||OnGUI TextField 控件

Unity 3D Color 控件与 Background Color 控件类似&#xff0c;都是渲染 GUI 颜色的&#xff0c;但是两者不同的是 Color 不但会渲染 GUI 的背景颜色&#xff0c;同时还会影响 GUI.Text 的颜色。具体使用时&#xff0c;要作如下定义&#xff1a;public static var color:Color;…

Go 管道关闭引发的探索

前言 在日常开发中, 经常会使用chan来进行协程之间的通信. 对chan的操作也无外乎读写关. 而本次, 就是从chan的关闭而来. 假设我们对外提供的方法如下: type Chan struct {ch chan int }func (c *Chan) Close() {close(c.ch) }func (c *Chan) Send(v int) {c.ch <- v }那…

Qt 工程师进阶技术23种设计模式

Qt 工程师进阶技术23种设计模式【1】23种设计模式【1】23种设计模式 设计模式是解决特定问题的一系列套路&#xff0c;这套方案提高代码可复用性、可读性、稳健性、可维护性及安全性。 23种设计模式可分为三类:结构型模式(侧重类与对象之间的组合)、行为型模式&#xff08;侧重…

day47【代码随想录】动态规划之买卖股票的最佳时机III、买卖股票的最佳时机IV、最佳买卖股票时机含冷冻期、买卖股票的最佳时机含手续费

文章目录前言一、买卖股票的最佳时机III&#xff08;力扣123&#xff09;二、买卖股票的最佳时机IV&#xff08;力扣188&#xff09;三、最佳买卖股票时机含冷冻期&#xff08;力扣309&#xff09;四、买卖股票的最佳时机含手续费&#xff08;力扣714&#xff09;股票买卖问题总…

office365 word 另存为 pdf 的注意事项和典型设置

0. 操作环境介绍 Office 版本&#xff1a;Office 365 版本 不同版本的操作可能有所不同 1. 基本操作 – 另存为 pdf 【文件】 --> 【另存为】&#xff0c;选择适当的文件路径、文件名保存类型选择【PDF】点击【保存】 1. 导出的pdf包含目录标签 word中&#xff0c;可使用…

Head First设计模式---1.策略模式

4.1策略模式&#xff1a; 策略模式是一种行为设计模式&#xff0c; 它能让你定义一系列算法&#xff0c; 并将每种算法分别放入独立的类中&#xff0c; 以使算法的对象能够相互替换。 问题 一天&#xff0c;我们需要做一个鸭子游戏&#xff0c;游戏中会出现各种鸭子&#xff…

掘金数据时代2022年度隐私计算评选活动火热报名中!

开放隐私计算 开放隐私计算开放隐私计算OpenMPC是国内第一个且影响力最大的隐私计算开放社区。社区秉承开放共享的精神&#xff0c;专注于隐私计算行业的研究与布道。社区致力于隐私计算技术的传播&#xff0c;愿成为中国 “隐私计算最后一公里的服务区”。183篇原创内容公众号…

全网最全虚拟机的封装

1.服务器初始化 系统环境RHEL7.6 2.禁用selinux [rootserver1 ~]# vim /etc/sysconfig/selinux SELINUXdisabled reboot 3.禁用防火墙 [rootserver1 ~]# systemctl disable --now firewalld 4.配置yum源 [rootserver1 ~]# vim /etc/fstab /dev/mapper/rhel…

AC的改进算法——TRPO、PPO

两类AC的改进算法 整理了动手学强化学习的学习内容 1. TRPO 算法&#xff08;Trust Region Policy Optimization&#xff09; 1.1. 前沿 策略梯度算法即沿着梯度方向迭代更新策略参数 。但是这种算法有一个明显的缺点&#xff1a;当策略网络沿着策略梯度更新参数&#xff0c…

(考研湖科大教书匠计算机网络)第五章传输层-第五节:TCP拥塞控制

获取pdf&#xff1a;密码7281专栏目录首页&#xff1a;【专栏必读】考研湖科大教书匠计算机网络笔记导航 文章目录一&#xff1a;拥塞控制概述二&#xff1a;拥塞控制四大算法&#xff08;1&#xff09;慢开始和拥塞避免A&#xff1a;慢启动&#xff08;slow start&#xff09;…

CTFer成长之路之举足轻重的信息搜集

举足轻重的信息搜集CTF 信息搜集 常见的搜集 题目描述: 一共3部分flag docker-compose.yml version: 3.2services:web:image: registry.cn-hangzhou.aliyuncs.com/n1book/web-information-backk:latestports:- 80:80启动方式 docker-compose up -d 题目Flag n1book{in…

设计模式-代理模式

控制和管理访问 玩过扮白脸&#xff0c;扮黑脸的游戏吗&#xff1f;你是一个白脸&#xff0c;提供很好且很友善的服务&#xff0c;但是你不希望每个人都叫你做事&#xff0c;所以找了黑脸控制对你的访问。这就是代理要做的&#xff1a;控制和管理对象。 监视器编码 需求&…