多線程(基礎)

??前言👀~

上一章我們介紹了什么是進程,對于進程就了解那么多即可,我們作為java程序員更關注線程,線程內容比較多,所以我們要分好幾部分才能講完

目錄

進程的缺點

?多線程(重要)

進程和線程的區別(經典面試題)

java如何進行多線程編程?

創建線程的方式(面試題)

繼承Thread類(來自java.lang包下)

使用匿名內部類繼承Thread類重寫run

實現Runnable接口

使用匿名內部類實現Runnable接口重寫run

使用lambda表達式創建線程(推薦)

Thread 類及常見方法

Thread類的構造方法

Thread類的常見屬性

啟動線程

中斷線程

等待線程

查看線程狀態


如果各位對文章的內容感興趣的話,請點點小贊,關注一手不迷路,如果內容有什么問題的話,歡迎各位評論糾正 🤞🤞🤞

12b46cd836b7495695ce3560ea45749c.jpeg

個人主頁:N_0050-CSDN博客

相關專欄:java SE_N_0050的博客-CSDN博客??java數據結構_N_0050的博客-CSDN博客? java EE_N_0050的博客-CSDN博客


進程的缺點

多進程編程的缺點:進程太重量效率不高,創建進程和銷毀進程和調度進程消耗的時間都是比較多的(消耗在申請資源上),因為我們知道進程是系統資源分配的基本單元,所以在給進程分配資源的時候是一個大活。拿分配內存說,操作系統內部也有一定的數據結構,用來管理空閑的內存,當進程申請內存空間的時候,操作系統就會從這個數據結構中找到大小合適空閑的內存返回給進程。這里的數據結構可以提高一定的效率,但是總體來說和線程相比還是比較耗時的。同時頻繁創建和銷毀進程和進程切換是一個開銷很大的操作,多進程和多線程都能實現并發編程,線程比進程更輕量。有些任務場景需要 “等待 IO”, 為了讓等待 IO 的時間能夠去做?些其他的工作, 也需要用到并發編程. 其次,雖然多進程也能實現 并發編程, 但是線程比進程更輕量


?多線程(重要)

進程想要執行任務就需要依賴線程線程不能獨立存在,需要依附于進程(進程包含線程,進程可包含一個線程也可包含多個線程),一個進程在最開始的時候,至少要有一個線程(主線程),這個線程負責完成執行代碼的工作,我們也可以根據需要創建多個線程,從而實現"并發編程"的效果換句話說,就是進程中的最小執行單位就是線程

線程也稱輕量級線程(創建、銷毀、調度都比進程快),每個線程就是一個獨立的 "執行流"(因為在執行用戶寫的代碼)可以獨立的執行一些代碼,每一個線程可以執行一系列的操作(也就是代碼)

更好的理解線程,還是拿之前在進程舉的演員的例子,一個舞臺可以有多個演員,但是呢這個多個演員來自不同的劇組,這里面的演員就是線程,劇組就是進程。在我們之前談的進程調度都是基于一個進程只有一個線程,可以理解為之前每個劇組都只有一個演員。實際上,一個進程可以有多個線程,每個線程都可以獨立進行調度。之后談到進程調度的話,不是調度整個進程,而是調度進程中的每一個線程。就比如說這個導演叫這個劇組的所有人來拍戲,所有的演員由導演進行分配角色、上場時間、臺詞等,相當于線程也有狀態、優先級、上下文、記賬信息

下面有圖更好理解多線程
?
一個工廠代表一個進程,一個生產線代表一個線程,我們之前提到的多進程是下面這樣子的?


下面這樣是我們說的多線程,一個進程中有多個線程,同個工廠(共用資源)兩個生產線(多線程)提高了效率


下面這么多人吃100個坤,適當的線程數目(里面的人)能提高效率,但是線程數目過多的情況,效率會降低并且造成線程沖突(線程不安全)


當人數過多且有人吃不到坤的時候,生氣了把雞全扔了,此時引發線程異常,如果我們沒有處理好,可能會導致整個進程崩了,其他線程也會隨之消失


總結:一個進程使用PCB來表示,一個進程可以使用一個PCB表示也可與使用多個PCB表示,每個TCB對應一個線程(可以理解PCB中包含TCB),并且每個線程都有這些信息(狀態、優先級、上下文、記賬信息,但每個線程有自己的程序計數器、虛擬機棧和本地方法棧)輔助調度,除此之外,前面說到的屬性pid是相同的,內存指針、文件描述符表也是共用一份的,根據這些信息我們可以得出線程的特點:每個線程都可以獨立去cpu上調度執行、同一個線程的多個進程之間共用一份內存空間和文件資源,所以我們創建線程的時候不需要像進程一樣申請資源(但是呢創建第一個線程的時候,相當于和進程一起創建的,所以我們要去申請資源,這里申請資源算在進程頭上。后續再創建線程的話就是共享同一份了),我們直接用系統給進程分配好的資源,這樣大大提高了我們的效率和節省開銷。綜上所述我們可以得出進程是資源分配的基本單位,線程是CPU 調度執行的基本單位

每個線程都是獨立調度的,在調度的過程中,系統就不考慮 進程 這樣的概念了。所以就是不同進程中的線程可以被輪番調度,每個線程只有獲得 CPU 的使用權才能執行指令。所謂多線程的并發運行,其實是指從宏觀上看,各個線程輪流獲得 CPU 的使用權,分別執行各自的任務。


進程和線程的區別(經典面試題)

1.線程比進程更輕量、高效,線程不需要申請資源,和同一進程共用一份,省去了申請資源的開銷

2.同一個進程內線程和線程之間會有影響(線程不安全和線程異常),一個線程崩了可能導致其他線程受到影響最終導致進程崩了。進程和進程之間具有獨立性

3.線程依附于進程,一個進程至少有一個線程(主線程),也可以有多個線程

4.線程是調度執行的基本單位,進程是資源分配的基本單位


java如何進行多線程編程?

線程是操作系統的概念,操作系統提供了一套API來操作線程,java對操作系統提供的API進行封裝(跨平臺),我們學java的只需要掌握java封裝過后的這套API就可以操作線程了

進程和進程之間能并發執行實現并發編程,線程和線程之間也能實現并發執行實現并發編程,我們學java的更側重線程之間的并發執行

創建線程的方式(面試題)

繼承Thread類(來自java.lang包下)

創建Thread對象,我們就可以操作 操作系統內部的線程了。以及重寫入口方法run(描述了該線程要執行的任務)

class MyThread extends Thread {@Overridepublic void run() {System.out.println("我開始工作了");System.out.println("我結束工作了");}
}public class test1 {public static void main(String[] args) {Thread thread = new MyThread();thread.start();System.out.println("我是主線程");}
}

輸出:不確定

再來看下面這段代碼,猜一下輸出順序

class MyThread extends Thread {@Overridepublic void run() {while (true) {System.out.println("thread線程正在工作");}}
}public class test1 {public static void main(String[] args) {Thread thread = new MyThread();thread.start();while (true) {System.out.println("主線程正在工作");}}
}

輸出:交替輸出


為什么呢?我們也不知道這兩個線程是同時執行的還是交替執行的(同一個核心上執行,還是分別在兩個核心上執行),所以我們統稱并發(并行+并發),實現并發編程的效果,為什么要實現并發編程?(充分利用多核cpu的資源)。

注意:打印順序不一定,操作系系統對于多個線程的調度順序是不確定的,隨機的。雖然有先后順序但是誰先誰后我們是不確定的(重要),這個隨機取決于操作系統對于線程調度的模塊(調度器)的具體實現

接著再來看下面這段代碼,猜一下輸出順序

class MyThread extends Thread {@Overridepublic void run() {while (true) {System.out.println("thread線程正在工作");}}
}public class test1 {public static void main(String[] args) {Thread thread = new MyThread();thread.run();while (true) {System.out.println("主線程正在工作");}}
}

輸出:thread線程正在工作? ?不只一條哈

原因:T.run 這種時候只有一個主線程,因為我們沒有創建一個新的進程。等run這個方法結束后,才會執行后面的代碼,相當于只有一個執行流,只能依次執行循環。相當于就是main線程在執行它的run方法,就跟我們在main方法中平常創建一個類然后調用方法一樣,main線程在工作

不信的話代碼拿去自己試試,然后用jdk中自帶的工具jconsole,里面其他線程是JVM創建的

使用匿名內部類繼承Thread類重寫run

同樣創建Thread對象,我們就可以操作 操作系統內部的線程了。以及重寫入口方法run(描述了該線程要執行的任務)

public class test1 {public static void main(String[] args) {Thread thread = new Thread() {@Overridepublic void run() {System.out.println("我是匿名內部類");}};thread.start();System.out.println("我是主線程");}
}

實現Runnable接口

實現Runnable接口,它就表示的是一個可以運行的任務,所以還是需要創建線程來完成這個任務。這樣理解我寫了個任務,丟給線程去完成,但是我們要先把線程創建出來才能去完成

class MyRunnable implements Runnable {@Overridepublic void run() {while (true) {System.out.println("我是Runnable接口");}}
}public class test1 {public static void main(String[] args) {MyRunnable myRunnable = new MyRunnable();Thread thread = new Thread(myRunnable);thread.start();while (true) {System.out.println("主線程正在工作");}}
}

使用Runnable接口和繼承Thread類的區別:主要是為了解耦合,使用Runnable接口相當于跟線程拆分開,把任務抽離出來,可以把這個任務丟給任意一個線程去完成,可以用在需要重復完成這個任務的場景,直接繼承Thread類就不行,它更適合完成一次性的任務

還有關于創建一個線程的時候,有兩個關鍵的操作。一個是明確線程要執行的任務,我們更關注任務本身,如果這個任務就只是執行一段簡單的代碼至于用什么方式實現這個任務沒什么區別。如果遇到復雜的任務有些方式可能就完成不了,這時候我們需要用其他的方式去完成,這時候我們把任務提取出來,我們可以自己選擇指定的方式去完成這個任務?? ?。另外一個操作就是通過調用系統API創建出線程。

使用匿名內部類實現Runnable接口重寫run

public class test1 {public static void main(String[] args) {Thread thread = new Thread(new Runnable() {@Overridepublic void run() {System.out.println("我是匿名內部類");}}) {};thread.start();System.out.println("我是主線程");}
}

使用lambda表達式創建線程(推薦)

public class test1 {public static void main(String[] args) {Thread thread = new Thread(() -> {System.out.println("我是lambda表達式");});thread.start();System.out.println("我是主線程");}
}

除了上面的方式之外,還有其他的方式,后續講解,還有一個點需要清楚就是創建Thread類的時候并沒有真正創建線程,只有在調用start方法的時候調用系統API去創建線程的時候才算認識


Thread 類及常見方法

Thread類的構造方法

在Thread類源碼里有個構造方法可以設置線程的名字,其他的就沒什么好介紹的了

public class test1 {public static void main(String[] args) {Thread thread = new Thread(() -> {while (true) {System.out.println("我是lambda表達式");}}, "我叫線程A");thread.start();}
}

為什么這里沒有顯示main線程呢?因為main線程執行完了,線程的入口方法執行完了,這個線程自然就銷毀了。對于主線程來說,入口方法就是main方法,它調用系統API去創建完線程之后就執行完了。所以如果線程都執行完了,進程也就結束了但只要有一個線程還在執行,進程就不會結束
?


Thread類的常見屬性


1.ID:線程的身份標識就是用來區分線程的,類似進程的pid,只不過這里的ID是java提供的,不是系統api提供的

2.getState()方法:獲取線程狀態,后面有講到

3.isDaemon()方法判斷是否為后臺線程(守護線程),守護線程就是用來告訴JVM,我的這個線程不重要不需要等待它運行完才退出,讓JVM喜歡什么時候退出就退出。前臺線程(非守護線程)就是告訴JVM,這個線程沒執行完成之前,你不能退出。默認情況一個線程是前臺線程守護進程(后臺進程),默認情況一個線程是前臺線程我們可以通過setDameon()方法去設置,這么設置之后主線程執行完后,沒有其他前臺線程了,這個進程自然也就結束了

public class test1 {public static void main(String[] args) {Thread thread = new Thread(() -> {while (true) {System.out.println("我是lambda表達式");}}, "我叫線程A");thread.setDaemon(true);//設置thread線程為守護線程thread.start();}
}

4.isAlive()方法:Thread對象的生命周期要比系統內核中的線程更長,線程沒了Thread對象還在,我們要以系統內核中的線程為主。所以我們使用isAlive()進行判斷,判斷系統內核中的線程有沒有結束,結束返回false,沒結束返回true。簡單的理解為 run 方法是否運行結束了

public class test1 {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}System.out.println("我是lambda表達式");}, "我叫線程A");System.out.println(thread.isAlive());thread.start();System.out.println(thread.isAlive());Thread.sleep(2000);System.out.println(thread.isAlive());}
}

輸出:false true 我是lambda表達式 false

5.isInterrupted()方法:用來判斷線程是否被中斷,怎么判斷呢?Thread內部有一個標志位進行判斷。下面會講到


啟動線程

使用start()方法創建線程

start方法和run方法的區別:非常直白的說,你可以把run看作是任務,start是叫人過來完成這個任務的。專業點說就是start方法通過調用系統API在系統內核中創建線程然后執行run方法中的代碼。run方法會在線程創建好后自動被被調用


中斷線程

中斷一個線程(終止/打斷),讓一個線程停止運行(銷毀),在java中銷毀/終止一個線程做法比較唯一(這個唯一不是說只有一個方法,而是說銷毀一個進程是讓run方法快點執行完),讓run方法快點執行完。在C++中是可以直接強制終止一個線程的運行,就比如你打開一個文本編輯器輸入一段信息,輸入一半直接給你干沒了

先補充兩個方法currentThread()方法和sleep()方法后面要用到

獲取當前線程引用:currentThread()方法返回當前線程對象的引用,哪個線程調用這個方法就獲取哪個線程對象的引用

休眠當前線程:sleep()方法讓線程睡覺的,你可以設置睡多久,然后時間到了系統把它叫醒(阻塞->就緒),注意睡醒之后不會馬上回到cpu上運行,要排隊,這里會涉及調度所以會有一定的開銷。就是你睡醒了需要一點時間緩緩才能去工作。

interrupt()方法:使用interrupt()方法設置標志位,前面說了Thread內部有一個標志位用來判斷線程是否結束,調用這個方法就把這個標志位設置成true。這樣即使我們還在執行sleep方法,它也會被強制喚醒。

來猜猜下面執行代碼線程會是什么狀態以及輸出什么

public class test1 {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {while (!Thread.currentThread().isInterrupted()) {System.out.println("hello");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});thread.start();Thread.sleep(3000);thread.interrupt();}
}

答案是輸出幾個hello后報異常,然后說說過程,這個線程先執行sleep方法,然后這個線程處于睡眠,然后你使用了interrupt()方法設置把標志位為true,把這個線程喚醒了,那么這個線程就會繼續工作,除非你不讓它睡眠并且設置標志位為true。舉個例子本來你在上班,然后突然有點困了,你同事讓你睡會,結果領導來了你同事趕緊把你叫醒,你立馬起來了。

使用interrupt()方法搭配sleep方法這樣設置的標志位就像沒效果一樣,沒有把你的線程中斷,為什么這樣設定呢?java期望線程收到中斷的信息的時候,我們能夠自己決定接下來要怎么處理,這樣可以讓我們在開發中有更多的操作空間,前提是通過異常的方式去喚醒。比如你打游戲女朋友叫你陪她去逛街,你可以直接關掉游戲陪她去,也可以說等我打完這把,還可以當個聾子啥也沒聽見。

public class test1 {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {while (!Thread.currentThread().isInterrupted()) {System.out.println("hello");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();
//            第一種   System.out.println("一直工作");
//                    
//            第二種   System.out.println("工作一會休息了");
//                    break;
//                    
//            第三種   break;}}});thread.start();Thread.sleep(3000);thread.interrupt();}
}

等待線程

使用join()方法,讓一個線程等待另外一個線程執行結束再執行。前面說線程并發執行的時候,執行的順序是不確定的隨機的,此時我們可以通過這個方法來控制線程結束的順序。并且我們可以設置等待時間,如果沒有設置等待時間,默認的話這個線程會一直等到那個線程執行結束后才會執行自己的任務,類似舔狗有一直舔的也有舔一段時間不舔了

join方法的工作過程:

1.如果主線程正在運行,主線程中調用了A.join方法,此時主線程進入阻塞狀態,A線程執行完,主線程才會解除完成接下來的任務

public class test1 {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {for (int i = 0; i < 5; i++) {System.out.println("我先干完活,你再干");}});thread.start();System.out.println("我要干活了");thread.join();System.out.println("輪到我干活了");}
}

輸出結果

2.如果主線程任務已經執行完了,再調用A.join方法,就不用進入阻塞狀態了,直接結束了

public class test1 {public static void main(String[] args) throws InterruptedException {Thread thread = new Thread(() -> {for (int i = 0; i < 5; i++) {System.out.println("我先干完活,你再干");}});thread.start();System.out.println("我馬上干完不給你機會干");thread.join();}
}

輸出結果


查看線程狀態

和進程一樣,線程也有運行、就緒、阻塞狀態。真正在系統調度的還是線程,線程是調度執行的基本單位

在java中,給線程賦予了一些其他的狀態:

1.NEW:Thread對象已經存在了,但是系統線程還沒創建,也就是還沒調用start方法

2.RUNNABLE:就緒狀態,這里有兩種表示,一種是在cpu上執行了,另一種是正等著去cpu上執行

3.TIMED_WATING:阻塞,被sleep這種固定時間的方式打斷產生的阻塞

4.WATING:阻塞,被wait這種不固定時間的方式打斷產生的阻塞

5.BLOCKED:阻塞,等待鎖導致的阻塞,后續死鎖講解

6.TERMINATED:Thread對象還在,操作系統內核的線程結束了,也這樣理解意味著該線程已經完成了其run方法的執行

public class test1 {public static void main(String[] args) throws InterruptedException {Thread t = new Thread(() -> {while (!Thread.currentThread().isInterrupted()) {System.out.println("java");try {Thread.sleep(2000);} catch (InterruptedException e) {break;}}});System.out.println(t.getState());//只創建了Thread對象的NEW狀態t.start();System.out.println(t.getState());//創建完線程t就是這個RUNNABLE狀態Thread.sleep(1000);System.out.println(t.getState());//t線程處于睡眠t.interrupt();Thread.sleep(1000);System.out.println(t.getState());//t線程執行完了}
}

輸出結果

后續線程出現卡死的情況,我們可以通過上述后面三種狀態去確定卡死的原因是什么,最后兩個狀態后續再講解

上述方法是多線程中非常常用的方法,要好好掌握,今天的內容就先到這,后面我們接著講解線程還有不少的知識點等著💕

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/36510.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/36510.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/36510.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

鴻蒙開發Ability Kit(程序框架服務):【FA模型切換Stage模型指導】 module的切換

module的切換 從FA模型切換到Stage模型時&#xff0c;開發者需要將config.json文件module標簽下的配置遷移到module.json5配置文件module標簽下&#xff0c;具體差異見下列表格。 表1 FA模型module標簽與Stage模型module標簽差異對比 FA標簽標簽說明對應的Stage標簽差異說明…

隨想錄 Day 72 拓撲排序、最短路徑 樸素dijkstra

隨想錄 Day 72 拓撲排序、最短路徑 樸素dijkstra 117. 軟件構建 117. 軟件構建 時間限制&#xff1a;1.000S 空間限制&#xff1a;256MB 題目描述 某個大型軟件項目的構建系統擁有 N 個文件&#xff0c;文件編號從 0 到 N - 1&#xff0c;在這些文件中&#xff0c;某些文件依…

LeetCode刷題之HOT100之課程表

吃完普通的食堂飯菜&#xff0c;回到實驗室&#xff0c;繼續做一道題&#xff01; 1、題目描述 2、邏輯分析 這道題涉及到圖相關知識&#xff0c;應用到了拓撲排序。 題意解釋 一共有 n 門課要上&#xff0c;編號為 0 ~ n-1。先決條件 [1, 0]&#xff0c;意思是必須先上課 0…

觸動心弦的成語之旅:《米小圈動畫成語》帶你走進中華智慧

成語&#xff0c;這些古老而典雅的語言精華&#xff0c;如同中華文化的晶瑩明珠&#xff0c;閃耀著歷史的光輝和智慧的火花。從古至今&#xff0c;它們在中國人的日常交流中扮演著重要角色&#xff0c;不僅傳遞著深刻的哲理和文化內涵&#xff0c;更是凝聚了世代智者的思想和智…

mindspore打卡第幾天 DDPM 之Unet 網絡解析markdown版本

mindspore打卡第幾天 DDPM 之Unet 網絡解析markdown版本 A: 為啥DDPM的unet網絡的下采樣這部分的channel是從20 32 64 128這樣上升的&#xff1f;從U形結構看不應該是下降的 &#xff5b;Block1 --> block2 --> Res&#xff08;attn&#xff09;-- >dowmsample&#…

20240622服務器異常

異常表現 玩法無法登錄服務器&#xff0c;遠程XShell 無法連接到服務器,IT 后臺查看服務器內存使用完畢。 異常處理 IT 直接重啟服務器 后續異常 Docker 服務器無法啟動 使用命令查看錯誤&#xff1a; sudo systemctl status docker.service docker.service - Docker Ap…

【Linux】線程id與互斥(線程三)

上一期我們進行了線程控制的了解與相關操作&#xff0c;但是扔就有一些問題沒有解決 本章第一階段就是解決tid的問題&#xff0c;第二階段是進行模擬一個簡易線程庫&#xff08;為了加深對于C庫封裝linux原生線程的理解&#xff09;&#xff0c;第三階段就是互斥。 目錄 線程id…

鏈在一起怎么聯機 鏈在一起遠程同玩聯機教程

steam中最近特別熱門的多人跑酷冒險的游戲&#xff1a;《鏈在一起》&#xff0c;英文名稱叫做Chained Together&#xff0c;在游戲中我們需要開始自己的旅程&#xff0c;在地獄的深處&#xff0c;與我們的同伴被鏈在一起。我們的任務是通過盡可能高的攀登逃離地獄。每一次跳躍都…

Python第三方庫GDAL 安裝

安裝GDAL的方式多種&#xff0c;包括pip、Anaconda、OSGeo4W等。筆者在安裝過程中&#xff0c;唯獨使用pip安裝遇到問題。最終通過輪子文件&#xff08;.whl&#xff09;成功安裝。 本文主要介紹如何下載和安裝較新版本的GDAL輪子文件。 一、GDAL輪子文件下載 打開Github網站…

Python學習打卡:day16

day16 筆記來源于&#xff1a;黑馬程序員python教程&#xff0c;8天python從入門到精通&#xff0c;學python看這套就夠了 目錄 day16116、SQL 基礎和 DDLSQL的概述SQL語言的分類SQL的語法特征DDL — 庫管理DDL — 表管理 117、SQL — DMLDML概述數據插入 INSERT數據刪除 DEL…

深入理解 Dubbo:分布式服務框架的核心原理與實踐

目錄 Dubbo 概述Dubbo 的架構Dubbo 的關鍵組件 服務提供者&#xff08;Provider&#xff09;服務消費者&#xff08;Consumer&#xff09;注冊中心&#xff08;Registry&#xff09;監控中心&#xff08;Monitor&#xff09;調用鏈追蹤&#xff08;Trace&#xff09; Dubbo 的…

電腦瀏覽器問題

網絡連接正常&#xff0c;但是瀏覽器就是打不開網頁&#xff0c;顯示未連接什么的。 搞了半天&#xff0c;不是代理服務器問題。 也不是端口問題。 也不是軟件版本問題。 竟然是瀏覽器插件的問題&#xff0c;插件禁用&#xff0c;奇跡般的好了。 參考&#xff1a; 電腦有網…

專題頁面設計指南:從構思到實現

如何設計專題頁&#xff1f;你有什么想法&#xff1f;專題頁的設計主要以發揚產品優勢為核心。一個好的專題頁可以從不同的角度向用戶介紹產品&#xff0c;擴大產品的相關優勢&#xff0c;表達產品的優勢&#xff0c;讓用戶在短時間內了解產品。因此&#xff0c;在設計詳細信息…

純血鴻蒙Beta版本發布,中國華為,站起來了!

2024年6月21日至23日&#xff0c;華為開發者大會2024&#xff08;HDC 2024&#xff09;于東莞盛大舉行。 此次大會不僅在會場設置了包括鴻蒙原生應用、統一生態統一互聯等在內的11個展區&#xff0c;以供展示HarmonyOS NEXT的強大實力&#xff0c;還對外宣布了HarmonyOS的最新進…

240627_關于CNN中圖像維度變化問題

240627_關于CNN中圖像維度變化問題 在學習一些經典模型時&#xff0c;其中得維度變化關系總搞不太明白&#xff0c;集中學習了以下&#xff0c;在此作以梳理總結&#xff1a; 一般來說涉及到的維度變換都是四個維度&#xff0c;當batch size4&#xff0c;圖像尺寸為640*640&a…

kylin v10 離線安裝chrome centos離線安裝chrome linux離線安裝谷歌瀏覽器

1. 先用自己聯網的計算機&#xff0c;下載離線安裝包&#xff0c;瀏覽器輸入鏈接下載安裝包&#xff1a; https://dl.google.com/linux/direct/google-chrome-stable_current_x86_64.rpm 1.2. 信創環境不用執行下面&#xff0c;因為沒網 1.3. 若為阿里云服務器&#xff0c;或服…

深度學習驅動的圖像識別革命

深度學習驅動的圖像識別革命正在徹底改變我們處理、分析和理解視覺信息的方式。以下是對這一革命的分點表示和歸納&#xff1a; 深度學習在圖像識別中的基本原理 特征提取&#xff1a;深度學習通過構建多層神經網絡&#xff0c;能夠自動從原始圖像數據中提取出復雜的特征&…

【第4章】MyBatis-Plus持久層接口之Service Interface(下)

文章目錄 前言一、get1. 示例(getById)2. 示例&#xff08;getOne&#xff09;3. 示例&#xff08;getOne 不拋出異常&#xff09;4. 示例&#xff08;getMap&#xff09;5. 示例&#xff08;getObj&#xff09; 二、list1. 示例&#xff08;list&#xff09;2. 示例&#xff0…

AR導航技術加持,圖書館閱讀體驗智慧升級

在信息爆炸的今天&#xff0c;圖書館作為知識的寶庫&#xff0c;其藏書量和種類日益增多。然而&#xff0c;傳統的圖書館導航方式已逐漸無法滿足用戶對快速、準確定位圖書的需求。本文將探討圖書館AR地圖導航的實現原理、技術優勢、功能特點以及市場前景&#xff0c;揭示為何AR…

VS studio2019配置遠程連接Ubuntu

VS studio2019配置遠程連接Ubuntu 1、網絡配置 &#xff08;1&#xff09;獲取主機IP &#xff08;2&#xff09;獲取Ubuntu的IP &#xff08;3&#xff09;在 windows 的控制臺中 ping 虛擬機的 ipv4 地址&#xff0c;在 Ubuntu 中 ping 主機的 ipv4 地址。 ubuntu: ping…