十五、多线程(基础)

news2024/12/23 13:56:55

文章目录

  • 一、线程介绍
    • 1.1 程序
    • 1.2 进程
    • 1.3 线程
  • 二、线程使用
    • 2.1 创建线程的两种方式
    • 2.2 继承Thread类创建线程
    • 2.3 实现Runnable接口创建线程
    • 2.4 多线程执行
    • 2.5 继承Thread vs 实现 Runnable的区别
    • 2.6 线程终止
  • 三、线程方法
    • 3.1 常用方法
    • 3.2 用户线程和守护线程
  • 四、线程生命周期
  • 五、Synchronized
    • 5.1 线程同步机制
    • 5.2 同步的原理
  • 六、互斥锁
  • 七、死锁
  • 九、释放锁
  • 八、细节
    • 8.1 互斥锁实现同步的机制
    • 8.2 使用继承`Thread`类的方式创建线程的互斥锁的问题

一、线程介绍

1.1 程序

在这里插入图片描述

1.2 进程

在这里插入图片描述

1.3 线程

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

二、线程使用

2.1 创建线程的两种方式

在这里插入图片描述

在这里插入图片描述

2.2 继承Thread类创建线程

在这里插入图片描述

在这里插入图片描述

package com.gyh.thread;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class Thread1 {
    public static void main(String[] args) throws InterruptedException {
        // 创建一个 Cat 对象,可以当成线程使用
        Cat cat = new Cat();

        // 源码解读
        /*

        (1)
        * public synchronized void start() {
        * ...
        *       start0();
        * ...
        * }
        *
        * start0() 是本地方法,是由JVM调用,底层是C/C++实现
        真正实现多线程的效果,是start0(),而不是 run 方法
            private native void start0();
        *
        *
        * */
        cat.start(); // 启动线程,最终会执行cat中的run方法


//        cat.run();// run方法就是一个普通的方法,没有真正的启动一个线程,就会把run方法执行完毕,才向下执行
        // 说明: 当 main 线程启动一个子线程后,主线程不会阻塞,会继续执行
        System.out.println("主线程继续执行" + Thread.currentThread().getName());
        for (int i = 0; i < 60; i++) {
            System.out.println("主线程 i=" + i);
            // 让主线程休眠
            Thread.sleep(1000);
        }
    }
}

// 解读
// 1. 当一个类继承了 Thread 类,该类就可以当做线程使用
// 2. 我们会重写 run 方法,写上自己的业务代码
// 3. run Thread 类 实现了 Runnable 接口的方法
/*
*   @Override
    public void run() {
        if (target != null) {
            target.run();
        }
    }
* */
class Cat extends Thread {
    @Override
    public void run() { // 重写run方法
        int n = 0;
        while (true) {
            // 该线程每隔1s,在控制台输出 "喵喵,我是小猫咪"
            System.out.println("喵喵,我是小猫咪" + (++n) + "线程名" + Thread.currentThread().getName());
            if (n == 80) break;
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

2.3 实现Runnable接口创建线程

在这里插入图片描述

在这里插入图片描述

package com.gyh.thread;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class Thread2 {
    public static void main(String[] args) {
        //dog.start(); // 这里不能调用start
        Dog dog = new Dog();
        Thread thread = new Thread(dog);
        thread.start(); // Thread内部使用了 静态代理的设计模式
    }
}

// 模拟Thread中的静态代理
class ThreadProxy implements Runnable {

    private Runnable target;

    @Override
    public void run() {
        if (target != null) target.run();
    }

    public ThreadProxy(Runnable target) {
        this.target = target;
    }

    public void start() {
         start0(); // 这个方法是真正实现多线程方法
    }

    public void start0() {
        run();
    }
}

class Dog implements Runnable { // 通过是实现Runnable接口,开发线程

    @Override
    public void run() { // 普通线程
        int count = 0;
        while (true) {
            System.out.println("小狗汪汪..hi" + (++count) + "Thread name:" + Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

2.4 多线程执行

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

package com.gyh.thread;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class Thread3 {
    public static void main(String[] args) {
        Thread01 thread01 = new Thread01();
        Thread02 thread02 = new Thread02();
        thread01.start();
        thread02.start();
    }
}

class Thread01 extends Thread {
    @Override
    public void run() {
        int count = 0;
        while (count < 10) {
            System.out.println("hello,world" + (++count) + "线程名:" + Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class Thread02 extends Thread {
    @Override
    public void run() {
        int count = 0;
        while (count < 5) {
            System.out.println("hi" + (++count) + "线程名:" + Thread.currentThread().getName());
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

2.5 继承Thread vs 实现 Runnable的区别

在这里插入图片描述

在这里插入图片描述

package com.gyh.thread;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class Thread4 {
    public static void main(String[] args) {
//        SellTicket01 sellTicket01 = new SellTicket01();
//        SellTicket01 sellTicket02 = new SellTicket01();
//        SellTicket01 sellTicket03 = new SellTicket01();
//
//        // 这里我们会出现超卖..
//        sellTicket01.start(); // 启动售票线程
//        sellTicket02.start(); // 启动售票线程
//        sellTicket03.start(); // 启动售票线程

        SellTicket2 sellTicket2 = new SellTicket2();
        new Thread(sellTicket2).start(); // 第一个线程--窗口
        new Thread(sellTicket2).start(); // 第二个线程--窗口
        new Thread(sellTicket2).start(); // 第三个线程--窗口
    }
}

// 继承Thread类
class SellTicket01 extends Thread {
    public static int ticketNum = 100;

    @Override
    public void run() {
        while (true) {
            if (ticketNum <= 0) {
                System.out.println("售票结束");
                break;
            }
            try {
                Thread.sleep(50);
                ticketNum--;
                System.out.println("还剩" + ticketNum + "张票");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class SellTicket2 implements Runnable {
    private static int ticketNum = 100;

    @Override
    public void run() {
        while (true) {
            if (ticketNum <= 0) {
                System.out.println("售票结束");
                break;
            }
            try {
                Thread.sleep(50);
                ticketNum--;
                System.out.println("还剩" + ticketNum + "张票");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

2.6 线程终止

在这里插入图片描述

在这里插入图片描述

package com.gyh.thread;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class Thread5 {
    public static void main(String[] args) {
        T t1 = new T();
        t1.start();

        // 如果希望main线程去控制 t1 线程的终止,唏嘘可以修改 loop
        // 让 t1 退出run方法,从而终止 t1线程 -> 通知方式
        try {
            System.out.println("主线程休眠10s");
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t1.setLoop(false);
    }
}

class T extends Thread {
    private int count = 0;
    // 设置一个控制变量
    private boolean loop = true;

    @Override
    public void run() {
        while (loop) {
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("T 运行中....");
        }
    }

    public void setLoop(boolean loop) {
        this.loop = loop;
    }
}

三、线程方法

3.1 常用方法

在这里插入图片描述

在这里插入图片描述

package com.gyh.thread;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class ThreadMethod {
    public static void main(String[] args) throws InterruptedException {
        T1 t = new T1();
        t.setName("老韩");
        t.setPriority(Thread.MIN_PRIORITY);
        t.start(); // 启动子线程

        System.out.println(t.getPriority());

        // 主线程打印 5 hi,然后我就终端 子线程的休眠
        for (int i = 0; i < 5; i++) {
            Thread.sleep(1000);
            System.out.println("hi " + i);
        }

        t.interrupt(); // 当执行到这里,就会终端 t线程的休眠
    }
}

class T1 extends Thread {
    @Override
    public void run() {
        while (true) {
            for (int i = 0; i < 100; i++) {
                // Thread.currentThread().getName() 获取当前线程的名称
                System.out.println(Thread.currentThread().getName() + "吃包子~~~~" + i);
            }

            try {
                System.out.println(Thread.currentThread().getName() + "休眠中~~~");
                Thread.sleep(20000); // 20s
            } catch (InterruptedException e) {
//                e.printStackTrace();
                // 当该线程执行到一个interrupt方法时,就会catch一个异常,可以加入自己的业务代码
                // InterruptedException 捕捉到一个中断异常
                System.out.println(Thread.currentThread().getName() + "被 interrupt了");
            }
        }
    }
}

在这里插入图片描述

package com.gyh.thread;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class Thread6 {
    public static void main(String[] args) throws InterruptedException {
        SubThread subThread = new SubThread();
        subThread.start();
        for (int i = 0; i < 20; i++) {
            System.out.println(Thread.currentThread().getName() + ":hi");
            Thread.sleep(1000);
            if (i == 4) subThread.join();
        }
    }
}

class SubThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 20; i++) {
            System.out.println(Thread.currentThread().getName() + "hello");
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

3.2 用户线程和守护线程

在这里插入图片描述

package com.gyh.thread;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class Thread7 {
    public static void main(String[] args) throws InterruptedException {
        ProtectSubThread protectSubThread = new ProtectSubThread();
        //如果我们希望当main线程结束后,子线程该自动结束
        // 只需要将子线程设置为守护线程即可
        protectSubThread.setDaemon(true);
        protectSubThread.start();
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + ":hi " + i);
            Thread.sleep(1000);
        }
    }
}

class ProtectSubThread extends Thread {
    @Override
    public void run() {
        while (true) {
            try {
                System.out.println(Thread.currentThread().getName() + ":hello");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

四、线程生命周期

在这里插入图片描述

在这里插入图片描述

package com.gyh.thread;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class Thread8 {
    public static void main(String[] args) throws InterruptedException {
        Runnable t = new Runnable() {
            @Override
            public void run() {
                while (true) {
                    for (int i = 0; i < 10; i++) {
                        System.out.println("hi " + i);
                        try {
                            Thread.sleep(1000);
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    break;
                }
            }
        };

        Thread thread = new Thread(t);
        System.out.println(thread.getName() + " 状态 " + thread.getState());
        thread.start();
        while (Thread.State.TERMINATED != thread.getState()) {
            System.out.println(thread.getName() + " 状态 " + thread.getState());
            Thread.sleep(500);
        }

        System.out.println(thread.getName() + " 状态 " + thread.getState());
    }
}

五、Synchronized

5.1 线程同步机制

在这里插入图片描述

在这里插入图片描述

package com.gyh.thread;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class Thread9 {
    public static void main(String[] args) {
        SubSellTicket subSellTicket = new SubSellTicket();
        new Thread(subSellTicket).start();
        new Thread(subSellTicket).start();
        new Thread(subSellTicket).start();
    }
}

// 实现接口方式,使用 synchronized 实现线程同步
class SubSellTicket implements Runnable {
    private static int ticketNum = 100;
    private boolean loop = true; // 设置结束条件

    public synchronized void sell() { // 同步方法, 在同一时刻,只能有一个线程老执行 run 方法
        if (ticketNum <= 0) {
            System.out.println("售票结束");
            return;
        }
        try {
            Thread.sleep(50);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        if (--ticketNum == 0) loop = false;
        System.out.println(Thread.currentThread().getName() + "通报,还剩" + ticketNum + "张票");
    }

    @Override
    public void run() {
        while (loop) {
            sell();
        }
    }
}

5.2 同步的原理

在这里插入图片描述

六、互斥锁

在这里插入图片描述

在这里插入图片描述

package com.gyh.thread;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class Thread9 {
    public static void main(String[] args) {
        SubSellTicket subSellTicket = new SubSellTicket();
        new Thread(subSellTicket).start();
        new Thread(subSellTicket).start();
        new Thread(subSellTicket).start();
    }
}

// 实现接口方式,使用 synchronized 实现线程同步
class SubSellTicket implements Runnable {
    private static int ticketNum = 100;
    private boolean loop = true; // 设置结束条件
    private final Object o = new Object();


    // 解读
    // 1. public synchronized static void m1(){} 锁是加在 SubSellTicket.class 对象上
    // 2. 如果在静态代码中,实现一个同步代码块
    /*
    *   synchronized (SubSellTicket.class){

        }
    *
    * */
    public synchronized static void m1(){

    }
    public static void m2(){
        synchronized (SubSellTicket.class){
            System.out.println("m2");
        }
    }


    // 解读:
    // 1. public synchronized void sell(){} 就是一个同步方法
    // 2. 这时锁是加在 this 对象上
    // 3. 也可以在代码块上写 synchronized ,同步代码块,互斥锁还是在 this 对象
    public /*synchronized*/ void sell() { // 同步方法, 在同一时刻,只能有一个线程老执行 run 方法
        synchronized (/*this*/ o) { // 同步代码块
            if (ticketNum <= 0) {
                System.out.println("售票结束");
                return;
            }
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (--ticketNum == 0) loop = false;
            System.out.println(Thread.currentThread().getName() + "通报,还剩" + ticketNum + "张票");
        }
    }

    @Override
    public void run() {
        while (loop) {
            sell();
        }
    }
}

七、死锁

在这里插入图片描述

package com.gyh.thread;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class Thread11 {
    public static void main(String[] args) {
        DeadLockDemo deadLockDemo1 = new DeadLockDemo(true);
        DeadLockDemo deadLockDemo2 = new DeadLockDemo(false);
        deadLockDemo1.start();
        deadLockDemo2.start();

    }
}

// 线程
class DeadLockDemo extends Thread {
    static Object o1 = new Object();// 保证多线程,共享一个对象
    static Object o2 = new Object();
    boolean flag;

    public DeadLockDemo(boolean flag) {
        this.flag = flag;
    }

    @Override
    public void run() {
        // 下面业务逻辑的分析
        // 1. 如果 flag 为 T,线程就会先得到/持有 o1 对象锁,然后尝试去获取 o2 对象锁
        // 2. 如果线程A 得不到 o2 对象锁,就会Blocked
        // 3. 如果flag 为 F,线程B 就会得到/持有 o2 对象锁
        // 4. 如果线程B 得不到 o1 对象锁,就会 Blocked
        if (flag) {
            synchronized (o1) { // 对象互斥锁,下面就是同步代码
                System.out.println(Thread.currentThread().getName() + "进入1");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (o2) { // 这里获得li对象的监视权
                    System.out.println(Thread.currentThread().getName() + "进入2");
                }
            }
        } else {
            synchronized (o2) {
                System.out.println(Thread.currentThread().getName() + "进入3");
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                synchronized (o1) { // 这里获得li对象的监视权
                    System.out.println(Thread.currentThread().getName() + "进入4");

                }
            }
        }
    }
}

九、释放锁

在这里插入图片描述

在这里插入图片描述

八、细节

8.1 互斥锁实现同步的机制

在这里插入图片描述

  • synchronized方法可以使用this对象的内部锁(互斥锁)来管理当前的方法,同一时刻该互斥锁控制只能有一个线程能够执行synchronized方法,因此该线程能执行代码,而其他线程由于访问不到该互斥锁因此被阻塞,待该互斥锁被释放后再次争夺互斥锁的访问权

8.2 使用继承Thread类的方式创建线程的互斥锁的问题

  • 由于继承 Thread 类的创建线程的方式,有多少个线程就会创建多少个对象,因此默认的同步方法对 this 上锁是不同的对象,不能实现同步
package com.gyh.thread;

/**
 * @author Gao YongHao
 * @version 1.0
 */
public class Thread10 {
    public static void main(String[] args) {
        new SubSellTicket1().start();
        new SubSellTicket1().start();
        new SubSellTicket1().start();

    }
}

// 实现接口方式,使用 synchronized 实现线程同步
class SubSellTicket1 extends Thread {
    private static int ticketNum = 100;
    private boolean loop = true; // 设置结束条件

    // 解读:
    // 1. public synchronized void sell(){} 就是一个同步方法
    // 2. 这时锁是加在 this 对象上
    // (但线程启动方式,每一个线程均会创建一个新的对象,这里的this在三个线程中指向各自的对象,因此不能实现同步)
    // 3. 也可以在代码块上写 synchronized ,同步代码块,互斥锁还是在 this 对象
    public /*synchronized*/ void sell() { // 同步方法, 在同一时刻,只能有一个线程老执行 run 方法
        synchronized (this) { // 同步代码块
            if (ticketNum <= 0) {
                System.out.println("售票结束");
                return;
            }
            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (--ticketNum == 0) loop = false;
            System.out.println(Thread.currentThread().getName() + "通报,还剩" + ticketNum + "张票");
        }
    }

    @Override
    public void run() {
        while (loop) {
            sell();
        }
    }
}

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

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

相关文章

MindSearch CPU-only 版部署

准备 创建环境 申请获取硅基流动 API Key 测试 hugging face 上传 /workspaces/codespaces-blank git clone https://huggingface.co/spaces/<你的名字>/<仓库名称>把token挂到仓库上&#xff0c;让自己有写权限 务必先初始化 git init git remote add space h…

打架监测识别摄像机

打架监测识别摄像机 是一种基于人工智能和图像识别技术的智能监控设备&#xff0c;旨在实时监测环境中的暴力冲突和打架行为。这种摄像机通常被广泛应用于监狱、学校、公共交通和其他管理需要的场所&#xff0c;以预防和控制不良事件的发生。 打架监测识别摄像机能够自动识别出…

try里面放return,finally还会执行吗?

引言 喜欢请点赞&#xff0c;支持点在看。 关注牛马圈&#xff0c;干货不间断。 趣聊 今天&#xff0c;在与同事讨论编程语言特性时&#xff0c;我们谈到了一个有趣的话题&#xff1a;在JavaScript中&#xff0c;finally块中的return语句是否会覆盖try块中的return。我首先通过…

【STM32项目设计】STM32F411健康助手--硬件SPI (硬件NSS/CS)驱动st7735--1.8寸TFT显示屏(1)

#include "lcd_driver.h"static uint16_t SPI_TIMEOUT_UserCallback(uint8_t errorCode);//液晶IO初始化配置 void LCD_Driver_Init(void) {SPI_InitTypeDef SPI_InitStructure;GPIO_InitTypeDef GPIO_InitStructure;/* 使能 LCD_SPI 及GPIO 时钟 *//*!< SPI_LCD…

程序员学CFA——财务报告与分析(七)

财务报告与分析&#xff08;七&#xff09; 存货存货的初始确认简介初始确认存货的初始入账成本费用化支出 发出存货的计量发出存货的计价方法个别计价法先进先出法后进先出法加权平均法总结对比 存货盘点方法实地盘存法永续盘存法总结归纳 后进先出法的特殊问题后进先出储备后…

安全测试|AWVS渗透测试神器工具详解,零基础入门到精通,收藏这一篇就够了

前言 Acunetix Web Vulnerability Scanner(简称AWVS)是一款知名的自动化网络漏洞扫描工具&#xff0c;它通过网络爬虫测试你的网站安全&#xff0c;检测流行安全漏洞。它可以扫描任何可通过Web浏览器访问的和遵循HTTP/HTTPS规则的Web站点和Web应用程序。适用于任何中小型和大型…

终于有人将多模态重点内容做成了动画

CLIP是入门多模态的最佳选择&#xff0c;后续多模态模型基本上都延续了它的思想&#xff1a;分别用图像编码器和文本编码器将图像和文本编码到一个共享的特征空间中&#xff0c;然后通过多模态融合方法将配对的图像文本特征向量拉进。 [1] 给定 ↳ 一个包含3个文本-图像对的小…

C++期末知识点概述

《大学 C知识点概述》 在大学的计算机课程中&#xff0c;C作为一门重要的编程语言&#xff0c;有着广泛的应用和丰富的知识点。 一、基础语法 数据类型&#xff1a;C包含多种数据类型&#xff0c;如整数类型&#xff08;int、short、long 等&#xff09;、浮点类型&#xff…

shell脚本编写之传参

我们知道命令可以带参数&#xff0c;同样脚本文件运行时也可以带有参数。 1、脚本内获取参数 脚本内获取参数的格式为&#xff1a;$n n代表一个数字&#xff0c;1 为执行脚本的第一个参数&#xff0c;2 为执行脚本的第二个参数&#xff0c;以此类推。 举例&#xff0c;仍然…

新手必看 | 信息收集打点篇

0x1 前言 本篇文章主要是汇总自己在以往的信息收集打点中的一些总结&#xff0c;然后给师傅们分享下个人信息打点的各种方式&#xff0c;以及使用工具的快、准、狠的重要性。让师傅们在后面的一些红队和众测包括src的项目中可以拿到一个不错的结果。 0x2 信息打点方向 探讨下…

天气数据爬取

目录 历史气象数据获取浏览器访问模拟 历史气象数据获取 主要的python包 requests BeautifulSoup re pandas lxml 浏览器访问模拟 根据浏览器Request-Header参数&#xff0c;让request模拟浏览器行为 import requests from bs4 import BeautifulSoup import re import pandas…

Qt 实战(10)MVD | 10.1、MVD机制详解

文章目录 一、MVD机制1、MVC设计模式1.1、简介1.2、优缺点分析 2、什么是MVD&#xff1f;2.1、简介2.2、核心角色 前言&#xff1a; 在Qt框架中&#xff0c;MVD&#xff08;Model-View-Delegate&#xff09;机制是一种用于实现数据与用户界面分离的重要设计模式。它源于经典的M…

python 下载油管视频的评论

先说结果: 2024年9月2日上午, 能运行&#xff01; 起因(目的): Not Like Us 这首歌&#xff0c; 1.5亿播放量&#xff0c;34万个评论。 有时候很想知道大家都说了什么。 Youtube 也是互联网的一霸&#xff0c; 大公司。 想爬人家的数据&#xff0c; 先做好失败的心理准备。 …

不同框架下跑yolov10(pt、onnx_runtime、tensorrt)

不同框架下跑yolov10&#xff08;pt、onnx_runtime、tensorrt&#xff09; (qq.com)

cmake版本升级 CMake Error: Could not find CMAKE_ROOT !!!

背景 ubuntu默认安装cmake较低版本,但是有些开发环境需要较高的版本,这时候需要手动升级一波. 1 官网获取cmake安装包 https://cmake.org/files/LatestRelease/,cmak官网下载 下载后,放到ubuntu里面,然后解压. tar zxvf *.gz 解压之后, cd cmake-3.30.0-Linux-x86_64/bin/, …

asp.net Temporary ASP.NET Files修改为其他位置

Temporary ASP.NET Files这个文件夹是编译期间用于临时文件存储的目录。当请求一个新页面时ASP.NET会分析aspx页面并为其生成一个.cs文件&#xff0c;然后JIT编译器会编译这个cs生成一个dll&#xff0c;这些过程都是在这个目录里面进行的。其中还放了你在项目中引用的Assembly的…

[CTF]-Pwn:做题笔记

seccon2018_kindvm解析&#xff08;vm&#xff09;&#xff1a; 查看保护 这里有两次输入。 完整exp&#xff1a; from pwn import* pprocess(./kindvm)p.sendlineafter(bInput your name :,bflag) payloadb\x01\x00\xff\xd8 payloadb\x02\xff\xdc\x00 payloadb\x06 p.sendl…

FastAPI+Vue3零基础开发ERP系统项目实战课 20240831上课笔记 查询参数和分页实现

回顾 获取路径参数什么是路径参数&#xff1f;/user/{id}什么时候使用&#xff1f;需要传递参数怎么实现类型转换&#xff1f;声明参数的类型怎么捕获文件路径&#xff1f;{file_path:path} 什么是查询参数 查询字符串是键值对的集合&#xff0c;这些键值对位于 URL 的 ? 之…

深兰科技荣登《2024胡润中国元宇宙潜力企业榜》Top100

8月29日&#xff0c;“胡润中国元宇宙高峰论坛”在广州南沙隆重召开。论坛期间&#xff0c;胡润研究院发布了《2024胡润中国元宇宙潜力企业榜》&#xff0c;列出了元宇宙领域最具发展潜力和影响力的中国企业&#xff0c;深兰科技成功入围《2024胡润中国元宇宙潜力企业榜》Top10…

基质粘弹性咋回事?与组织生长啥关系?快来看看!

大家好&#xff0c;今天我们要来了解一个关于细胞外基质的有趣话题——《Matrix viscoelasticity controls spatio-temporal tissue organization》发表于《Nature materials》。细胞外基质的粘弹性对组织的时空组织起着重要作用&#xff0c;但这一作用尚未被完全理解。我们将通…