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.pswp.cn/diannao/41407.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/41407.shtml
英文地址,請注明出處:http://en.pswp.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;…