java并发编程 JUC-基础篇 快速入门

1.进程与线程的概念

(1)进程

程序有指令与数据组成,指令要运行,数据要读写,就必须指令加载到CPU。数据加载到内容,指令运行需要用到磁盘。

当一个程序被运行时,从磁盘加载这个程序的代码至内存,这时开启了一个进程。

(2)线程

一个进程之内可以分为一个或多个线程。

一个线程就是一个指令流,将指令流中的一条条指令以一定的顺序交给CPU执行。

Java中的 最小调度单位是线程,最小资源分配单位是进程。

2.并发与并行的概念

并发:同一时间应对多件事情的能力。

并行:同一时间动手做多件事情的能力。

3.异步与同步的概念

异步:不需要等待结果返回,就能继续运行

同步:需要等待结果返回,才能继续运行

同步在多线程中是让多个线程步调一致

4.多线程提高效率的结论

(1)单核CPU下,多线程不能实际提高程序运行效率,只是为了能够在不同任务之间切换,不同

线程轮流使用CPU,不至于一个线程总是占用一个CPU,别的线程没法干活。

(2)多核CPU下,可以并行运行多个线程,能否提高效率要分情况:

一些任务可以通过设计,将任务拆分,并行执行,可以提高运行效率。

不是所有任务都需要拆分,任务的目的不同。

(3)IO操作不占用CPU,只是我们一般拷贝文件使用的是 阻塞IO,相当于线程虽然不用CPU,但是需要等待IO结束,没能充分利用线程,才有了 非阻塞IO异步IO 优化

5.创建线程

5.1 Thread的方式

        Thread thread = new Thread(){@Overridepublic void run(){System.out.println("Hello JUC");}};thread.start();

5.2 Runnable的方式

        Runnable runnable = new Runnable(){@Overridepublic void run(){System.out.println("Hello JUC Runnable");}};Thread thread = new Thread(runnable);thread.start();

5.3 Lambda的方式

5.3.1 Thread的Lambda写法

        Thread thread = new Thread(()->{ System.out.println("Hello JUC Lambda");});thread.start();

5.3.2 Runnable的Lambda写法

        Runnable runnable = ()->{System.out.println("Hello JUC Lambda");};Thread thread = new Thread(runnable);thread.start();

5.4 FutureTaks 配合 Thread

FutureTasks 能够接收Callable类型的参数,用于·处理有返回结果的情况

    @Testvoid testFutureTask() throws ExecutionException, InterruptedException {FutureTask<Integer> task = new FutureTask<>(new Callable<Integer>() {@Overridepublic Integer call() throws Exception {System.out.println("Running ...");Thread.sleep(3000);return 100;}});Thread thread = new Thread(task);thread.start();System.out.println(task.get());}

6.线程运行

线程运行现象:线程运行交替执行。谁先谁后,不由我们所控制。

查询线程的方式:

(1)windows:

可以通过任务管理器查看进程和线程数

tasklilst 查看进程

taskkill 杀死进程

(2)linux:

ps -fe 查看所有进程

ps -fT -p <PID> 这将显示PID进程及其所有线程的详细信息。

kill 杀死进程

top 按大写H切换是否显示线程

top -H -p <PID> 查看某个进程(PID)

(3)Java:

jps 命令查看所有Java进程

jstack <PID> 查看某个Java进程(PID)的所有线程状态

jconsole 来查看某个Java进程中线程的运行情况

7.线程运行的原理

7.1栈帧

JVM是由堆、栈、方法区所组成的,其中栈内存 存放就是线程,每个线程启动后,虚拟机就会分配一块栈内存。

每个栈有多个栈帧,对应着每次方法调用时所占用的内存。

每个线程只有一个活动栈帧,对应着当前正在执行的那个方法。

7.2上下文切换(Thread Context Switch)

可能因为

  • 线程的cpu时间用完
  • 垃圾回收
  • 有更高优先级的线程需要运行
  • 线程自己调用了sleep、yield、wait、join、park、synchronized、lock等方法

当Thread Context Switch发送时,需要操作系统保存当前线程的状态,并恢复另一个线程的状态,Java中对应的概念就是程序计数器,它的作用记录下一条jvm指令的执行地址,是线程私有的。

状态包括程序计数器,虚拟机中每个栈帧的信息,如局部变量,操作数栈,返回地址等

Thread Context Switch频繁发生会影响性能

8.线程中的常见方法

方法描述
start()启动新线程并执行该线程的run()方法。线程开始执行时,它的run()方法会被调用。
run()当线程启动时,run()方法会被调用。这个方法应该包含线程的执行代码。
join()等待调用join()方法的线程终止。例如,thread.join()会使当前线程等待thread线程终止。
sleep(long millis)使当前线程暂停执行指定的毫秒数。线程不会失去任何监视器的所有权。
interrupt()中断线程。如果线程在调用Object类的wait()wait(long)wait(long, int)join()join(long, int)或者sleep(long, int)方法时被阻塞,那么它的中断状态将被清除,并且它将接收到InterruptedException
isAlive()测试线程是否处于活动状态。如果线程已经启动且尚未终止,则线程处于活动状态。
setName(String name)改变线程的名称,可以通过getName()方法获取线程的名称。
getPriority()返回线程的优先级。线程的优先级可以设置为MIN_PRIORITY(1)、NORM_PRIORITY(5)或MAX_PRIORITY(10)。
setPriority(int newPriority)变线程的优先级。线程优先级只是建议给调度器,实际调度可能会忽略它。
yield()暂停当前正在执行的线程对象,并执行其他线程。
getState()返回线程的状态。线程的状态可以是NEWRUNNABLEBLOCKEDWAITINGTIMED_WAITINGTERMINATED
isInterrupted()测试线程是否已经中断。不同于interrupted()方法,这个方法不会改变线程的中断状态。

8.1 run 与 start 的区别

(1)run() 方法:

  • run() 方法是线程的执行主体,它包含了线程要执行的任务。
  • 当线程被启动时,run() 方法会被自动调用。
  • run() 方法可以直接调用,就像调用普通方法一样,它在当前线程中执行,而不是在新线程中执行。
  • 如果直接调用 run() 方法,程序不会创建新的线程,而是在当前线程中顺序执行 run() 方法中的代码。

(2)start() 方法:

  • start() 方法用于启动一个新线程,并执行该线程的 run() 方法。
  • 当 start() 方法被调用时,Java 虚拟机会创建一个新的线程,并执行 run() 方法中的代码。
  • start() 方法只能被调用一次,多次调用会抛出 IllegalThreadStateException
  • 调用 start() 方法后,线程可能会立即开始执行,也可能因为线程调度器的安排而在稍后执行。

8.2 Sleep和yield的区别

(3)Sleep

  • 调用sleep让当前线程从Running进入Timed Waiting(阻塞)状态
  • 其他线程可以通过interrupt方法打断正在睡眠的线程,这时sleep方法会抛出InterruptedException
  • 睡眠解释后的线程未必会立即执行
  • 建议使用Timeunit的sleep代替Thread的sleep,有更好的可读性

(4)yield

  • 调用yield 会使当前线程从Running进入Runnable就绪状态,然后调度执行其他线程
  • 具体的实现依赖操作系统的任务调度器
  • 在Java中,Thread.yield()也是一个静态方法,它使当前线程从运行状态转到可运行状态,但不会释放所占有的任何资源。
  • 通常,yield的使用并不频繁,因为它对线程调度提供的信息有限,且线程调度器可能会忽略这个提示。

8.3 线程优先级

  • 线程优先级会提示调度器优先调度线程
  • 如果CPU比较忙,那么优先级高的线程会获得更多的时间片;如果CPU比较空闲,优先级几乎没有什么作用。

8.4 Sleep实现

在没有利用CPU实现计算时,不要让while(true)空转浪费CPU,这时可以使用yield或sleep使CPU的使用权让给其他的程序

8.5 join实现

等待thread线程运行结束或终止。

如果join(long n)带参数的话,就是等待线程运行结束的最多等待n毫秒

8.6 打断阻塞

阻塞

打断sleep的线程,清空打断状态

示例:

  @Testvoid test() throws ExecutionException, InterruptedException {Thread t1 = new Thread(()->{try{TimeUnit.SECONDS.sleep(12);}catch (Exception e){e.printStackTrace();}},"t1");t1.start();TimeUnit.SECONDS.sleep(2);t1.interrupt();System.out.println(t1.isInterrupted());}

注意: 使用 isInterrupted()来判断是否打断成功,对于打断sleep的结果为false则表示打断成功,同理wait和join都是false标记为打断成功。

8.7 打断正常

打断正常的则isInterrupted()为true则表示打断成功

示例:

    @Testvoid test() throws  InterruptedException {Thread t1 = new Thread(()->{try{while (true){boolean interrupted = Thread.currentThread().isInterrupted();if (interrupted){log.info("打斷...");break;}}}catch (Exception e){e.printStackTrace();}},"t1");t1.start();TimeUnit.SECONDS.sleep(3);log.info("interrupt");t1.interrupt();}

9.两阶段终止

问题:在一个线程T1中如何优雅的终止线程T2呢?

错误的思路:

  • 使用stop方法终止线程,这种如果此时线程锁住了公共享资源,将其杀死后就再也没有机会释放资源,导致其他线程永远无法获取锁。
  • 使用System.exit(int)方法停止线程,目的是仅停止一个线程,但是会让整个程序都停止

正确的思路:

    @Testvoid test() throws  InterruptedException {Thread t1 = new Thread(()->{while (true){Thread current = Thread.currentThread();if(current.isInterrupted()){log.info("打断....");break;}try {Thread.sleep(800);log.info("正在记录中.....");}catch (InterruptedException e){e.printStackTrace();//重置设置打断标识,因为sleep过程中进行interrupt是标识false,那么需要正常的interrupt使其标识为truecurrent.interrupt();}}});t1.start();TimeUnit.SECONDS.sleep(3);t1.interrupt();}

10.打断park线程

打断线程后不会影响标记

11.不推荐的方法

这些方法过时,容易破坏同步代码块,造成线程死锁

方法名说明
stop()停止线程运行
suspend()挂起(暂停)线程运行
resume()恢复线程运行

12.主线程与守护线程

默认情况下,Java进程需要等待线程运行都结束,才会结束。有一种特殊的线程是守护线程,只要其他的线程运行结束了,即使守护线程的代码还没有执行结束,也会强制结束。

示例:设置t1线程为守护线程:

t1.setDaemon(true);

运用:

  • 垃圾回收器线程就是一种守护线程
  • 接收shutdown命令后,不会等待Acceptor和Poller守护线程处理完当前请求

13.线程的五种状态

五种状态:初始状态、可运行状态、运行状态、终止状态、阻塞状态

  • 初始状态:仅在语言层面创建了线程对象,还未与操作系统线程关联
  • 可运行状态;也称(就绪状态),指线程已经被创建(与操作系统线程未关联),可以由CPU调度执行
  • 运行状态:指获取CPU时间片运行中的状态
  • 阻塞状态:如果调用了阻塞API,这时线程实际不会用到CPU,会导致线程上下文切换,进入阻塞状态
  • 终止状态:表示线程已经执行完毕,生命周期已经结束,不会转换为其他状态


14.共享资源的线程安全(synchronized)

竞态条件:发生在至少两个线程竞争同一资源时,而最终的结果取决于这些线程的执行顺序。在大多数情况下,竞态条件的出现是由于程序设计上的缺陷,例如没有适当的同步机制来控制对共享资源的访问。

为了避免临界的竞态的条件发生,可以使用以下的手段实现:

  • 阻塞式的解决方案:Synchronized,Lock
  • 非阻塞式的解决方案:原子变量

使用阻塞式的解决方案:Synchronized(对象锁),采用互斥的方式让同一时刻至多只有一个线程能持有 对象锁,其他线程再想获取这个 对象锁 就会被阻塞住。这样可以保证线程可以安全的执行临界区内的代码,不用担心线程的上下文切换

  • 互斥是保证临界区的竞态条件发生,同一时刻只有一个线程执行临界区代码
  • 同步是由于线程执行的先后,顺序不同,需要一个线程等待其他线程运行到某个点

 示例代码:

    int counter = 0;Object lock = new Object();@Testvoid test() throws  InterruptedException {Thread t1 = new Thread(()->{for (int i = 0;i<=50000;i++){synchronized(lock){counter++;}}});Thread t2 = new Thread(()->{for (int i = 0;i<=50000;i++){synchronized(lock){counter--;}}});t1.setName("t1");t2.setName("t2");t1.start();t2.start();t1.join();t2.join();log.info("Counter:{}",counter);}

synchronized用对象锁保证了临界区内代码的原子性,临界区的代码对外不可分割,不会被线程切换所打断

思考:

如果synchronized(obj)放在for循环外面,如何理解? --原子性

如果 t1 synchronized(obj1) 而 t2 synchronized(obj2) 会怎么运行?--锁对象

如果 t1 synchronized(obj)而 t2没有加会怎么样?--锁对象

14.1 通过面向对象的方式实现:

创建实体:

public class Room {private int counter = 0;public void increment(){synchronized (this){counter++;}}public void decrement(){synchronized (this){counter--;}}public int getCounter(){synchronized (this){return counter;}}
}

实现代码:

    Room room = new Room();@Testvoid test() throws  InterruptedException {Thread t1 = new Thread(()->{room.increment();});Thread t2 = new Thread(()->{room.decrement();});t1.setName("t1");t2.setName("t2");t1.start();t2.start();t1.join();t2.join();log.info("Counter:{}",room.getCounter());}

      14.2 synchronized加在方法上

(1)

public class Test {public synchronized void test(){}}

相当于:

public class Test {public  void test(){synchronized(this){}}}

(2)static方法

public class Test {public synchronized static void test(){}}

相当于:

public class Test {public  static void test(){synchronized(Test.class){}}}

15.变量线程安全分析

15.1 成员变量和静态变量是否线程安全?

(1)如果没有共享,则线程安全

(2)如果共享,根据他们的状态是否能够改变,分为两种情况:

  • 如果只有读操作,则线程安全
  • 如果有读写操作,则这段代码是临界区,需要考虑线程安全

15.2 局部变量是否线程安全?

(1)局部变量是线程安全的

(2)但是局部变量引用的对象则未必

  • 如果该对象没有逃离方法的作用访问,它是线程安全的
  • 如果该对象逃离方法的作用范围,则需要考虑线程安全

16.常用的线程安全类

  • String
  • Integer
  • StringBuffer
  • Random
  • Vector
  • Hashtable
  • java.utils.concurrent包下的类

这里的线程安全是多线程调用它们同一个实例的某个方法时,线程是安全的。可以理解为

  • 它们的每个方法是原子
  • 但是它们的多个方法的组合不是原子的(不是线程安全的)

不可改变线程安全

String、Integer等都是不可变类,因为其内部的状态不可改变,因此它们的方法都是线程安全的

虽然String有replace、substring等方法可以改变值、但是根据源码可知都是创新一个新的对象,没有改变原有的对象的值,所以线程安全

17.买票问题习题

(1)线程安全问题示例

package org.example;import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Vector;// 主类,用于执行售票模拟
public class ExerciseSell {// 执行售票模拟的入口点public static void main(String[] args) throws InterruptedException {// 创建一个 TicketWindow 实例,初始票数为1000TicketWindow ticket = new TicketWindow(1000);// 创建一个线程列表,用于存放即将创建的线程List<Thread> threadList = new ArrayList<>();// 创建一个Integer类型的列表,用于存放每个线程卖出的票数List<Integer> amountList = new Vector<>();// 创建80000个线程,每个线程将模拟卖出一定数量的票for(int i = 0; i < 80000; i++) {Thread thread = new Thread(() -> {// 每个线程卖出的票数是随机生成的int amount = ticket.sell(randomAmount());try {// 模拟售票操作后的延迟Thread.sleep(10);} catch (InterruptedException e) {// 如果线程在睡眠中被中断,抛出运行时异常throw new RuntimeException(e);}// 将卖出的票数添加到amountList中amountList.add(amount);});// 将新创建的线程添加到线程列表中threadList.add(thread);// 启动线程thread.start();}// 等待所有线程完成for (Thread thread : threadList) {thread.join();}// 打印剩余票数System.out.println("余票:" + ticket.getAmount());// 计算所有线程卖出的票数总和并打印System.out.println("卖出的票数:" + amountList.stream().mapToInt(i -> i).sum());}// 生成随机售票数的方法static Random random = new Random();public static int randomAmount() {// 返回1到5之间的随机整数,包括1和5return random.nextInt(5) + 1;}
}// 表示售票窗口的类
class TicketWindow {// 私有属性,表示售票窗口的票数private int amount;// 构造函数,初始化票数为传入的参数public TicketWindow(int amount) {this.amount = amount;}// 获取当前票数的方法public int getAmount() {return amount;}// 售票方法,尝试从窗口卖出指定数量的票public int sell(int amount) {if (this.amount >= amount) {// 如果票数足够,减少票数并返回卖出的票数this.amount -= amount;return amount;} else {// 如果票数不足,返回0return 0;}}
}

(2)解决线程安全问题方法

这段代码存在线程安全问题。具体来说,TicketWindow 类的 amount 成员变量在被多个线程访问和修改时,没有使用任何同步机制,这可能导致多个线程同时修改 amount,从而引发数据不一致的问题。

所以要给amount 进行共享资源读写的时进行加锁操作(这段代码,只需要对sell方法加上synchronized即可加锁)

 public synchronized int sell(int amount){if(this.amount >= amount){this.amount -= amount;return amount;}else {return 0;}}

18. 转账习题

(1)线程安全问题示例
 

package org.example;import java.util.Random;public class ExerciseTransfer {public static void main(String[] args) throws InterruptedException {Amount a = new Amount(1000);Amount b = new Amount(1000);Thread t1 = new Thread(()->{for(int i = 0;i < 100;i++){a.transfer(b,randomAmount());}});Thread t2 = new Thread(()->{for(int i = 0;i < 100;i++){b.transfer(a,randomAmount());}});t1.start();t2.start();t1.join();t2.join();System.out.println("总金额:"+a.getMoney() + b.getMoney());}static Random random = new Random();public static int randomAmount(){return random.nextInt(100) + 1;}}class Amount{private int money;public int getMoney() {return money;}public void setMoney(int money) {this.money = money;}public Amount(int money) {this.money = money;}public void transfer(Amount amount,int transferMoney){if(this.money >= transferMoney){this.setMoney(this.getMoney() - transferMoney);amount.setMoney(amount.getMoney() + transferMoney);}}
}

(2)解决线程安全问题方法(两个共享变量)

    public void transfer(Amount amount,int transferMoney){synchronized(Amount.class){if(this.money >= transferMoney){this.setMoney(this.getMoney() - transferMoney);amount.setMoney(amount.getMoney() + transferMoney);}}}

 因为如果

public synchronized  void transfer(Amount amount,int transferMoney){if(this.money >= transferMoney){this.setMoney(this.getMoney() - transferMoney);amount.setMoney(amount.getMoney() + transferMoney);}}

相当于保护this.money,但是不保护amount的money

    public void transfer(Amount amount,int transferMoney){synchronized(this){if(this.money >= transferMoney){this.setMoney(this.getMoney() - transferMoney);amount.setMoney(amount.getMoney() + transferMoney);}}}

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

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

相关文章

探索Vue Router:构建高效单页面应用的指南

引言 Vue Router&#xff0c;作为Vue.js的官方路由管理器&#xff0c;为构建SPA提供了强大的支持 Vue Router 基础 Vue Router 的基本概念和作用 Vue Router 是一个用于构建单页面应用的 Vue.js 插件。它允许我们通过定义路由规则来将不同的 URL 映射到不同的组件&#xff…

1023记录

米哈游二面 自动化测试中自动化驱动的能力&#xff1f; pytest的驱动能力&#xff1a; 1&#xff0c;自动发现测试用例&#xff1a;以"test_"开头的Python文件、以"Test"开头的类和以"test_"开头的函数&#xff0c;将它们识别为测试用例 2&…

植物大战僵尸融合版最新版1.0下载及安装教程

《植物大战僵尸融合版》最新版1.0已经发布&#xff0c;为粉丝们带来了全新的游戏体验。这个版本由B站UP主蓝飘飘fly精心打造&#xff0c;引入了创新的植物融合玩法&#xff0c;让玩家可以享受策略和创意的结合。以下是游戏的详细介绍和安装指南&#xff1a; 游戏特色介绍 全新…

基于深度学习的图像背景剔除

在过去几年的机器学习领域&#xff0c;我一直想打造真正的机器学习产品。 几个月前&#xff0c;在参加了精彩的 Fast.AI 深度学习课程后&#xff0c;似乎一切皆有可能&#xff0c;我有机会&#xff1a;深度学习技术的进步使许多以前不可能实现的事情成为可能&#xff0c;而且开…

Java--继承

1.继承的本质是对某一批类的抽象&#xff0c;从而实现对世界更好的建模 2.extends的意思是“扩展”&#xff0c;子类是父亲的扩展 3.Java中只有单继承&#xff0c;没有多继承 4.继承关系的两个类&#xff0c;一个为子类&#xff08;派生类&#xff09;&#xff0c;一个为父类…

QML-Grid和OpacityMask

一个格子条&#xff0c;点击缩短 import QtQuick 2.0 import QtQuick.Window 2.12 import QtQuick.Controls 2.5 //导入 import QtGraphicalEffects 1.12Window {id:windowwidth: 600height: 500color: "white"visible: trueGrid {visible: falseid:gridwidth:405he…

STAR 命令参数解释

以这个为例子解释STAR参数含义 STAR 命令参数解释 STAR \ --outFilterType BySJout \ --runThreadN 8 \ --outFilterMismatchNmax 2 \ --genomeDir <hg19_STARindex> \ --readFilesIn <un_aligned.fastq> \ --outFileNamePrefix <HEK293> \ --outSAMtype B…

欧科云链大咖对话:Web3原生创新静默期,科技巨头却在两极化发展

出品&#xff5c;OKG Research 作者&#xff5c;Hedy Bi 上周末&#xff0c;欧科云链研究院接受FT中文的邀请&#xff0c;作为圆桌嘉宾参与了由FT中文网与上海交通大学上海高级金融学院联合主办的金融大师课。在圆桌环节&#xff0c;笔者与各位教授和金融行业科技创新前沿实践…

案例精选 | 聚铭网络助力南京市玄武区教育局构建内网日志审计合规体系

南京市玄武区教育局作为江苏省教育领域的先锋机构&#xff0c;其工作重点涵盖了教育政策的实施、教育现代化与信息化的融合、教育资源的优化、教育质量的提升以及教育公平的促进。在这一背景下&#xff0c;网络安全管理成为了确保教育信息化顺利推进的关键环节之一。 根据玄武…

Nacos单机部署、集群部署以及Nacos默认持久化derby数据库和配置mysql数据库

1. Nacos Windows 下载 1.1 去nacos官网下载nacos-server 发布历史 | Nacos 官网https://nacos.io/download/release-history/ 下载版本为 nacos-server-2.3.1.zip 2. Derby数据库 2.1 默认使用Derby数据库 官网下载Derby数据库即可。 Apache Derby数据库https://db.apac…

昇思25天学习打卡营第9天|MindSpore使用静态图加速(基于context的开启方式)

在Graph模式下&#xff0c;Python代码并不是由Python解释器去执行&#xff0c;而是将代码编译成静态计算图&#xff0c;然后执行静态计算图。 在静态图模式下&#xff0c;MindSpore通过源码转换的方式&#xff0c;将Python的源码转换成中间表达IR&#xff08;Intermediate Repr…

VSCode远程服务器

一、安装VSCode Windows安装Visual Studio Code(VS Code)-CSDN博客 二、VSCode中安装Remote-SSH插件 1、在应用商店中搜索Remote - SSH并安装 2、安装后会出现下面标注的图标 三、开始SSH连接 1、点击加号&#xff0c;创建SSH连接 2、输入地址&#xff0c;格式是&#xff1a;…

服务器部署 tomcat mysql nginx配置安装

一、安装配置tomcat 下载并解压 Tomcat 首先,从 Apache Tomcat 官方网站下载最新版本的 Tomcat。以 Tomcat 9 为例:下载慢的话,也可以本地上传到root目录下进行解压 sudo wget https://dlcdn.apache.org/tomcat/tomcat-9/v9.0.58/bin/apache-tomcat-9.0.58.tar.gz sudo tar …

文件打开的系统错误分析流程

当用户出现“Open file failed”错误时&#xff0c;手动产生dump文件。 &#xff08;1&#xff09;打开资源管理器&#xff0c;选择AppNameXXX.exe进程&#xff0c;右击鼠标选择“创建转储文件” (2) 生成转储文件 3.获取用户转储文件 4.用Visual studio2015打开dump文件分析…

人工智能系列-numpy(三)

&#x1f308;个人主页&#xff1a;羽晨同学 &#x1f4ab;个人格言:“成为自己未来的主人~” 副本和视图 副本 副本是一个数据的完整的拷贝&#xff0c;如果我们对副本进行修改&#xff0c;它不会影响到原始数据&#xff0c;物理内存不再同一位置。副本一般发生在Pytho…

MySQL——statement对象详解

JDBC中的statement对象用于向数据库发送SQL语句&#xff0c;想完成对数据库的增删改查&#xff0c;只需要通过这个对象向数据库发送增删改查语句即可。 Statement对象的executeUpdate方法&#xff0c;用于向数据库发送增、删、改的sql语句&#xff0c;executeUpdate执行完成后…

Vue前端打包

关于NGINX 介绍:Nginx是一款轻量级的Web服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器。其特点是占有内存少&#xff0c;并发能力强&#xff0c;在各大型互联网公司都有非常广泛的使用。 NGiMx 官网:https://nginx.org/ conf 配置文件目录 html静态资源文件目录 lo…

华为OD面试分享18

2024年OD统一考试(D卷)完整题库:华为OD机试2024年最新题库(Python、JAVA、C++合集) 正文开始 7月3日上午一面 问项目 String变量直接引用和new一个String变量的区别 谈谈多线程 canel的工作原理 MVC的执行过程 redis怎么用的 编程题-网络连通区域数量 7月3日晚上二面 编程…

html+js+css在线倒计时

代码在图片后面 点赞加关注 谢谢大佬照顾&#x1f61c; 图例 时间到前 时间到后 源代码 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content"widthdevice-width,…

10.09面试题目记录

艾融软件 - 线上面试题 排序算法的时间复杂度 O(n^2&#xff09;&#xff1a;冒泡&#xff0c;选择&#xff0c;插入 O(logn&#xff09;&#xff1a;折半插入排序 O(nlogn)&#xff1a;希尔&#xff0c;归并&#xff0c;快速&#xff0c;堆 O(nk)&#xff1a;桶&#xff0c;…