成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

拜托!別再問(wèn)我多線程的這些問(wèn)題了

網(wǎng)絡(luò) 通信技術(shù)
很多同學(xué)面對(duì)多線程的問(wèn)題都很頭大,因?yàn)樽约鹤鲰?xiàng)目很難用到,但是但凡高薪的職位面試都會(huì)問(wèn)到。。畢竟現(xiàn)在大廠里用的都是多線程高并發(fā),所以這塊內(nèi)容不吃透肯定是不行的。

[[340332]]

本文轉(zhuǎn)載自微信公眾號(hào)「碼農(nóng)田小齊」,作者小齊本齊 。轉(zhuǎn)載本文請(qǐng)聯(lián)系碼農(nóng)田小齊公眾號(hào)。  

很多同學(xué)面對(duì)多線程的問(wèn)題都很頭大,因?yàn)樽约鹤鲰?xiàng)目很難用到,但是但凡高薪的職位面試都會(huì)問(wèn)到。。畢竟現(xiàn)在大廠里用的都是多線程高并發(fā),所以這塊內(nèi)容不吃透肯定是不行的。

今天這篇文章,作為多線程的基礎(chǔ)篇,先來(lái)談?wù)勔韵聠?wèn)題:

  • 為什么要用多線程?
  • 程序 vs 進(jìn)程 vs 線程
  • 創(chuàng)建線程的 4 種方式?

為什么要用多線程

任何一項(xiàng)技術(shù)的出現(xiàn)都是為了解決現(xiàn)有問(wèn)題。

之前的互聯(lián)網(wǎng)大多是單機(jī)服務(wù),體量小;而現(xiàn)在的更多是集群服務(wù),同一時(shí)刻有多個(gè)用戶同時(shí)訪問(wèn)服務(wù)器,那么會(huì)有很多線程并發(fā)訪問(wèn)。

比如在電商系統(tǒng)里,同一時(shí)刻比如整點(diǎn)搶購(gòu)時(shí),大量用戶同時(shí)訪問(wèn)服務(wù)器,所以現(xiàn)在公司里開(kāi)發(fā)的基本都是多線程的。

使用多線程確實(shí)提高了運(yùn)行的效率,但與此同時(shí),我們也需要特別注意數(shù)據(jù)的增刪改情況,這就是線程安全問(wèn)題,比如之前說(shuō)過(guò)的 HashMap vs HashTable,Vector vs ArrayList。

要保證線程安全也有很多方式,比如說(shuō)加鎖,但又可能會(huì)出現(xiàn)其他問(wèn)題比如死鎖,所以多線程相關(guān)問(wèn)題會(huì)比較麻煩。

因此,我們需要理解多線程的原理和它可能會(huì)產(chǎn)生的問(wèn)題以及如何解決問(wèn)題,才能拿下高薪職位。

進(jìn)程 vs 線程

程序program

說(shuō)到進(jìn)程,就不得不先說(shuō)說(shuō)程序。

程序,說(shuō)白了就是代碼,或者說(shuō)是一系列指令的集合。比如「微信.exe」這就是一個(gè)程序,這個(gè)文件最終是要拿到 CPU 里面去執(zhí)行的。

進(jìn)程 process

當(dāng)程序運(yùn)行起來(lái),它就是一個(gè)進(jìn)程。

所以程序是“死”的,進(jìn)程是“活”的。

比如在任務(wù)管理器里的就是一個(gè)個(gè)進(jìn)程,就是“動(dòng)起來(lái)”的應(yīng)用程序。

 

Q:這些進(jìn)程是并行執(zhí)行的嗎?

單核 CPU 一個(gè)時(shí)間片里只能執(zhí)行一個(gè)進(jìn)程。但是因?yàn)樗袚Q速度很快,所以我們感受不到,就造成了一種多進(jìn)程的假象。(多核 CPU 那真的就是并行執(zhí)行的了。)

Q:那如果這個(gè)進(jìn)程沒(méi)執(zhí)行完呢?

當(dāng)進(jìn)程 A 執(zhí)行完一個(gè)時(shí)間片,但是還沒(méi)執(zhí)行完時(shí),為了方便下次接著執(zhí)行,要保存剛剛執(zhí)行完的這些數(shù)據(jù)信息,叫做「保存現(xiàn)場(chǎng)」。

然后等下次再搶到了資源執(zhí)行的時(shí)候,先「恢復(fù)現(xiàn)場(chǎng)」,再開(kāi)始繼續(xù)執(zhí)行。

這樣循環(huán)往復(fù)。。

這樣反復(fù)的保存啊、恢復(fù)啊,都是額外的開(kāi)銷,也會(huì)讓程序執(zhí)行變慢。

Q:有沒(méi)有更高效的方式呢?

如果兩個(gè)線程歸屬同一個(gè)進(jìn)程,就不需要保存、恢復(fù)現(xiàn)場(chǎng)了。

這就是 NIO 模型的思路,也是 NIO 模型比 BIO 模型效率高很多的原因,我們之后再講。

線程 thread

線程,是一個(gè)進(jìn)程里的具體的執(zhí)行路徑,就是真正干活的。

在一個(gè)進(jìn)程里,一個(gè)時(shí)間片也只能有一個(gè)線程在執(zhí)行,但因?yàn)闀r(shí)間片的切換速度非常快,所以看起來(lái)就好像是同時(shí)進(jìn)行的。

一個(gè)進(jìn)程里至少有一個(gè)線程。比如主線程,就是我們平時(shí)寫(xiě)的 main() 函數(shù),是用戶線程;還有 gc 線程是 JVM 生產(chǎn)的,負(fù)責(zé)垃圾回收,是守護(hù)線程。

 

每個(gè)線程有自己的棧 stack,記錄該線程里面的方法相互調(diào)用的關(guān)系;

但是一個(gè)進(jìn)程里的所有線程是共用堆 heap 的。

那么不同的進(jìn)程之間是不可以互相訪問(wèn)內(nèi)存的,每個(gè)進(jìn)程有自己的內(nèi)存空間 memeory space,也就是虛擬內(nèi)存 virtual memory。

通過(guò)這個(gè)虛擬內(nèi)存,每一個(gè)進(jìn)程都感覺(jué)自己擁有了整個(gè)內(nèi)存空間。

虛擬內(nèi)存的機(jī)制,就是屏蔽了物理內(nèi)存的限制。

Q:那如果物理內(nèi)存被用完了呢?

用硬盤(pán),比如 windows 系統(tǒng)的分頁(yè)文件,就是把一部分虛擬內(nèi)存放到了硬盤(pán)上。

相應(yīng)的,此時(shí)程序運(yùn)行會(huì)很慢,因?yàn)橛脖P(pán)的讀寫(xiě)速度比內(nèi)存慢很多,是我們可以感受到的慢,這就是為什么開(kāi)多了程序電腦就會(huì)變卡的原因。

Q:那這個(gè)虛擬內(nèi)存是有多大呢?

對(duì)于 64 位操作系統(tǒng)來(lái)說(shuō),每個(gè)程序可以用 64 個(gè)二進(jìn)制位,也就是 2^64 這么大的空間!

如果還不清楚二進(jìn)制相關(guān)內(nèi)容的,公眾號(hào)內(nèi)回復(fù)「二進(jìn)制」獲取相應(yīng)的文章哦~

總結(jié)

總結(jié)一下,在一個(gè)時(shí)間片里,一個(gè) CPU 只能執(zhí)行一個(gè)進(jìn)程。

CPU 給某個(gè)進(jìn)程分配資源后,這個(gè)進(jìn)程開(kāi)始運(yùn)行;進(jìn)程里的線程去搶占資源,一個(gè)時(shí)間片就只有一個(gè)線程能執(zhí)行,誰(shuí)先搶到就是誰(shuí)的。

 

多進(jìn)程 vs 多線程

每個(gè)進(jìn)程是獨(dú)立的,進(jìn)程 A 出問(wèn)題不會(huì)影響到進(jìn)程 B;

雖然線程也是獨(dú)立運(yùn)行的,但是一個(gè)進(jìn)程里的線程是共用同一個(gè)堆,如果某個(gè)線程 out of memory,那么這個(gè)進(jìn)程里所有的線程都完了。

所以多進(jìn)程能夠提高系統(tǒng)的容錯(cuò)性 fault tolerance ,而多線程最大的好處就是線程間的通信非常方便。

進(jìn)程之間的通信需要借助額外的機(jī)制,比如進(jìn)程間通訊 interprocess communication -IPC,或者網(wǎng)絡(luò)傳遞等等。

如何創(chuàng)建線程

上面說(shuō)了一堆概念,接下來(lái)我們看具體實(shí)現(xiàn)。

Java 中是通過(guò) java.lang.Thread 這個(gè)類來(lái)實(shí)現(xiàn)多線程的功能的,那我們先來(lái)看看這個(gè)類。

從文檔中我們可以看到,Thread 類是直接繼承 Object 的,同時(shí)它也是實(shí)現(xiàn)了 Runnable 接口。

官方文檔里也寫(xiě)明了 2 種創(chuàng)建線程的方式:

一種方式是從 Thread 類繼承,并重寫(xiě) run(),run() 方法里寫(xiě)的是這個(gè)線程要執(zhí)行的代碼;

啟動(dòng)時(shí)通過(guò) new 這個(gè) class 的一個(gè)實(shí)例,調(diào)用 start() 方法啟動(dòng)線程。

 

二是實(shí)現(xiàn) Runnable 接口,并實(shí)現(xiàn) run(),run() 方法里同樣也寫(xiě)的是這個(gè)線程要執(zhí)行的代碼;

稍有不同的是啟動(dòng)線程,需要 new 一個(gè)線程,并把剛剛創(chuàng)建的這個(gè)實(shí)現(xiàn)了 Runnable 接口的類的實(shí)例傳進(jìn)去,再調(diào)用 start(),這其實(shí)是代理模式。

 

如果面試官問(wèn)你,還有沒(méi)有其他的,那還可以說(shuō):

實(shí)現(xiàn) Callable 接口;

通過(guò)線程池來(lái)啟動(dòng)一個(gè)線程。

但其實(shí),用線程池來(lái)啟動(dòng)線程時(shí)也是用的前兩種方式之一創(chuàng)建的。

這兩種方式在這里就不細(xì)說(shuō)啦,我們具體來(lái)看前兩種方式。

繼承 Thread 類

  1. public class MyThread extends Thread { 
  2.     @Override 
  3.     public void run() { 
  4.         for (int i = 0; i < 100; i++) { 
  5.             System.out.println("小齊666:" + i); 
  6.         } 
  7.     } 
  8.     public static void main(String[] args) { 
  9.         MyThread myThread = new MyThread(); 
  10.         myThread.start(); 
  11.         for (int i = 0; i < 100; i++) { 
  12.             System.out.println("主線程" + i + ":齊姐666"); 
  13.         } 
  14.     } 

在這里,

  • main 函數(shù)是主線程,是程序的入口,執(zhí)行整個(gè)程序;
  • 程序開(kāi)始執(zhí)行后先啟動(dòng)了一個(gè)新的線程 myThread,在這個(gè)線程里輸出“小齊”;
  • 主線程并行執(zhí)行,并輸出“主線程i:齊姐”。

 

來(lái)看下結(jié)果,就是兩個(gè)線程交替夸我嘛~

 

Q:為啥和我運(yùn)行的結(jié)果不一樣?

多線程中,每次運(yùn)行的結(jié)果可能都會(huì)不一樣,因?yàn)槲覀儫o(wú)法人為控制哪條線程在什么時(shí)刻先搶到資源。

當(dāng)然了,我們可以給線程加上優(yōu)先級(jí) priority,但高優(yōu)先級(jí)也無(wú)法保證這條線程一定能先被執(zhí)行,只能說(shuō)有更大的概率搶到資源先執(zhí)行。

實(shí)現(xiàn) Runnable 接口

這種方式用的更多。

  1. public class MyRunnable implements Runnable { 
  2.     @Override 
  3.     public void run() { 
  4.         for(int i = 0; i < 100; i++) { 
  5.             System.out.println("小齊666:" + i); 
  6.         } 
  7.     } 
  8.  
  9.     public static void main(String[] args) { 
  10.         new Thread(new MyRunnable()).start(); 
  11.  
  12.         for(int i = 0; i < 100; i++) { 
  13.             System.out.println("主線程" + i + ":齊姐666"); 
  14.         } 
  15.     } 

結(jié)果也差不多:

 

像前文所說(shuō),這里線程啟動(dòng)的方式和剛才的稍有不同,因?yàn)樾陆ǖ牡倪@個(gè)類只是實(shí)現(xiàn)了 Runnable 接口,所以還需要一個(gè)線程來(lái)“代理”執(zhí)行它,所以需要把我們新建的這個(gè)類的實(shí)例傳入到一個(gè)線程里,這里其實(shí)是代理模式。這個(gè)設(shè)計(jì)模式之后再細(xì)講。

小結(jié)

那這兩種方式哪種好呢?

使用 Runnable 接口更好,主要原因是 Java 單繼承。

另外需要注意的是,在啟動(dòng)線程的的時(shí)候用的是 start(),而不是 run()。

調(diào)用 run() 僅僅是調(diào)用了這個(gè)方法,是普通的方法調(diào)用;而 start() 才是啟動(dòng)線程,然后由 JVM 去調(diào)用該線程的 run() 。

 

好了,以上就是多線程第一篇的所有內(nèi)容了,這里主要是幫助大家復(fù)習(xí)一下基礎(chǔ)概念,以及沒(méi)有接觸過(guò)多線程的小伙伴可以入門(mén)。想看更多關(guān)于多線程的文章的話,記得給我點(diǎn)贊留言哦~

 

責(zé)任編輯:武曉燕 來(lái)源: 碼農(nóng)田小齊
相關(guān)推薦

2018-09-28 05:25:53

TopK算法代碼

2020-04-22 11:19:07

貪心算法動(dòng)態(tài)規(guī)劃

2018-11-01 13:49:23

桶排序排序面試

2018-10-28 22:37:00

計(jì)數(shù)排序排序面試

2018-11-06 11:40:19

時(shí)間復(fù)雜度面試算法

2021-01-22 10:09:23

簡(jiǎn)歷求職者面試

2019-04-16 13:30:05

表達(dá)式求值數(shù)據(jù)結(jié)構(gòu)算法

2020-03-30 17:20:54

B+樹(shù)SQL索引

2019-01-08 15:11:50

最大值最小值算法

2022-03-14 10:14:43

底層系統(tǒng)Nacos

2018-11-09 09:34:05

面試Spring Clou底層

2019-08-29 09:49:50

2020-12-11 09:24:19

Elasticsear存儲(chǔ)數(shù)據(jù)

2020-09-24 14:40:55

Python 開(kāi)發(fā)編程語(yǔ)言

2020-04-16 08:22:11

HTTPS加解密協(xié)議

2015-02-13 10:42:31

前端工具Dreamweaver

2019-07-10 10:06:24

面試官三次握手四次揮手

2019-12-17 09:29:02

數(shù)據(jù)庫(kù)架構(gòu)分庫(kù)分表

2020-11-02 11:21:35

Python編輯器代碼

2019-03-12 14:48:29

路由器XBOXPS4
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 91在线免费视频 | 精品免费国产视频 | 自拍偷拍亚洲欧美 | 亚洲自拍偷拍免费视频 | 国产激情一区二区三区 | 亚洲高清视频在线观看 | 久久亚洲一区 | 亚洲欧洲小视频 | 国产精品久久久久久久久久免费看 | 久久婷婷麻豆国产91天堂 | 国产欧美二区 | 日韩精品三区 | 日韩免费一区二区 | www.亚洲一区 | 亚洲天堂一区二区 | 日韩欧美国产一区二区 | 成人在线视频免费看 | 中文字幕在线一区二区三区 | 人人操日日干 | 精品国产一区二区三区久久 | 日韩www视频 | 成人免费网站 | 国产精品视频中文字幕 | 国产成人精品999在线观看 | 国产精品日韩欧美一区二区三区 | 国产精品欧美日韩 | 玖玖在线精品 | 久久久新视频 | 99re视频这里只有精品 | 超碰97人人人人人蜜桃 | 精品少妇一区二区三区在线播放 | 久久av一区 | 一区二区三区视频在线观看 | 亚洲第一av | 欧美日韩国产高清 | 日韩精品 电影一区 亚洲 | 在线播放国产一区二区三区 | 国产成人av免费看 | 91免费高清视频 | 九色av| 欧美日韩国产一区二区 |