中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

java虛擬機中多線程是怎樣總結的

發布時間:2021-10-13 16:42:19 來源:億速云 閱讀:129 作者:柒染 欄目:編程語言

本篇文章為大家展示了java虛擬機中多線程是怎樣總結的,內容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細介紹希望你能有所收獲。

我記得最開始接觸多進程,多線程這一塊的時候我不是怎么理解,為什么要有多線程啊?多線程到底是個什么鬼啊?我一個程序好好的就可以運行為什么要用到多線程啊?反正我是十分費解,即使過了很長時間我還是不是很懂,聽別人說過也自己試過,但總是沒有理解透徹;

時間過了很久感覺現在對多線程有了一點新的理解,我們還是從最基本的開始,順便看看從jvm的角度看看多線程在jvm中是怎么分配內存的,順便和前面的幾篇內容串一下;

1.現實中的多線程

舉個例子:假如你一個人在家,你現在聽首歌5分鐘,燒開水需要10分鐘,玩一局游戲要20分鐘,現在問題來了,你完成這三件事總共需要多少分鐘?

假如是小學生肯定會回答5+10+20=35分鐘啊,但我們比小學生牛一點,稍微思考一下就知道是20分鐘,因為三件事可以同時做嘛,玩游戲的同時可以聽歌,順便燒開水,一把游戲打完,歌聽完了,水也燒開然后可以去泡茶了,舒服!

我們用一個比較簡陋的圖看看這兩種方式(這里先不考慮并發與并行的區別,方便理解)

可以粗略的看到如果是小學生的話,要一件事一件事的做,最后花的時間是三者時間總和;而我們比較聰明,由于三件事互不影響,我們可以三件事同時開始做,這樣就大大減少了不必要的等待時間,最終三者花費的時間差不多就是最長的那一個。

這里稍微提一下并發和并行的區別;

并發:這個是在計算機單核CPU的前提之下,我們要清楚一個CPU在某一時刻只能做一件事,但是現在有三件事(聽歌,燒開水,玩游戲)交給CPU做,CPU是個好人,任勞任怨,一下子去聽歌,一下子去燒開水,一下子玩游戲,最終可以把三件事都給做完,但是假如同時有幾百件事交給CPU做呢?emmmm,最后CPU就被累垮了,住院去了,于是我們計算機也卡死了;舉個最貼近我們的例子:以前上學的時候作業太多,很多時候都是很多科目的作業都沒有做完,那怎么辦呢?只有早上去早點去抄一下同學的,但是各個課代表來收作業了,于是只能這個科目作業抄一點馬上又把另外一個科目作業抄一點,瑪德,最后終于在規定時間都抄完了,可是假如你有100個科目的作業沒做完,你會怎么辦?用命去抄也抄不完了,于是你就累病了。。。。

并行:多核CPU的前提,現在一個電腦都有多個CPU,那么CPU同時就可以做多件事,即使事情再多,多個CPU進行切換最終花費的時間確實大大減少;還是說說上面抄作業的例子,假如你現在有10門科目的作業沒做完,就靠你一個頭腦一只手肯定來不及啊!于是這個時候你喚醒了前世的記憶,原來你是哪吒轉世,特么的居然可以變成是三頭六臂,這得可以同時抄多少份作業啊!!!一下子作業就做完了,舒服!但是這個時候作業科目太多的話你即使有三頭六臂也不夠用啊,而且相互之間的協調也就變成一個很重要的問題。

并發和并行就是這個意思,我們現在只關注并發,看看在單核CPU的計算機中一個程序是怎么運行的?

2.進程和線程

想想什么叫做進程呢?我的理解就是程序進入了內存就是進程,比如我們電腦桌面雙擊QQ,優酷,java虛擬機等,操作系統就會把這些軟件的內容加載到內存中去運行去了,然后就是運行某編程語言寫的代碼,轉化為機器碼調用操作系統的接口,然后操作系統的內核會那些硬件驅動程序發出一些指令,然后我們的電腦屏幕就出現變化了。。。我們簡單畫一畫圖,我們主要看JVM

我們再進入JVM中看看,其中線程1、2、3就是我們在java代碼中要去實現的;

進程:我們百度一下進程的定義,最重要的一點就是進程是操作系統資源分配的基本單位,因為每啟動一個程序,一個進程就創建了,在操作系統堆內存空間上就開辟了一塊空間,也就是分配了資源。

線程:現在再來看線程,百度一下線程定義,其實就是說:進程就是一個程序,這個程序之中可能會同時執行多個任務的代碼,每一個任務就是一個線程,而且每一個線程都會在JVM中有自己獨立的java棧,pc寄存器,而且CPU只能切換線程,即使是不同程序的線程也可以相互切換。

這里就要說明一下,想比進程和線程,創建一個進程是要在操作系統內存中去開辟空間,會涉及到對操作系統一些函數的調用,而創建一個線程(比如在JVM中)只需要在jvm中個部分開辟空間,相比較之下,肯定是創建線程所耗費的操作系統資源比較少,但是也不可能無限制的創建很多線程,不然jvm也會出問題!

我隨便查了一下,一般的web服務器線程數最大不能超過CPU核數*50,如:8核<300,16核<800,根據實際情況還可以適當調一下。

記得有句話叫做多個線程之間會競爭CPU資源這句話當初我可是很久都沒有理解,這競爭CPU資源到底什么鬼?CPU的資源到底是什么啊?emmmm..

記得以前家里比較窮,沒有像現在一樣手機電腦這么多,家里只有一個電視!但是有的時候家里人每個人喜歡看的節目都不一樣,于是不可避免的相互之間就為了爭這個遙控器而發生沖突,哈哈哈!這個時候遙控器就相當于CPU,我們每個人都相當于一個線程要完成自己的事情。但是遙控器就一個,就會相互搶遙控器,有的時候我搶過來遙控器看火影忍者沒到一分鐘,就被我姐搶去看美食節目,沒過一會兒遙控器就被我爸搶去看新聞去了。。。。。

3.java中的多線程用法

java之中用多線程主要是3種方式:類,接口,線程池,接下來我們就隨意看一下這三種方式

3.1.類

這種方式主要是繼承Thread類,實現run()方法,run()方法就是我們所需要做的任務的邏輯代碼,然后將這個類實例化調用start()方法,表示現在這個線程隨時可以被CPU調用;

我還是以上面玩游戲,燒開水和聽歌為例,隨意寫個小例子:

注意:這里先不看GC,前臺線程有四個線程,我們創建的三個,還有執行main方法的這個線程(這個也叫主線程),我們只能保證主線程最優先運行,至于這四個線程哪個先停止,隨機。。。

3.2.接口

這種方式也差不多,實現Runnable接口,實現其中的run()方法,然后實例化這個對象并傳入Thread類中,再調用start()方法;

3.3.線程池

什么是線程池呢?你看看我們上面寫的創建線程的方法,都是用的時候就去創建,用完了就銷毀,下次又要用就又去創建,這種做法很不好,因為每次創建和銷毀線程都是很消耗jvm內部資源的,因為在jvm內部會進行申請空間,分配空間和釋放空間各種操作,對jvm的性能會有一定的影響,而且假如某個特殊的情況下每個線程只會運行很短的時間就會結束,那么就會十分頻繁的常見和銷毀線程,導致在jvm中頻繁的申請和釋放內存,這極大的影響jvm的運行性能。

但是啊,如果我們能在程序啟動的時候,就先創建一定數量的線程放在一個池子里,我們要用的話就去拿,用完了就再放到池子里,這樣就很好的避免了創建和銷毀線程的過程,這種方式比較友好;其中這個存放線程的池子就叫做線程池,接下來我們隨意看看線程池的用法:

順便一提,利用線程池執行線程任務有兩種方式,一種是我們用的pool.execute(xxxx),另外一種是pool.submit(xxxx),用法和參數都一樣,區別是用submit()提交內部其實還是調用execute(),而且還可以獲取線程執行后的返回值,后面我們會分析到的;

線程池起到一個類似緩沖的作用,它可以對池子中的線程數目進行控制,想想,假如我們程序直接創建線程那可能會由于創建線程太多導致jvm崩潰,但是我們有一個確定容量的池子,我們不用擔心這個池子會炸了,我們只需要從池子里拿就好了,至于拿不拿得到的問題后面我們會好好分析的;

3.4.看看Callable接口

這個接口干嘛的呢?有了Runnable接口了,還要這個接口干嘛?

不知道有沒有注意到那個Runnable接口的run()方法是沒有返回值的,也就是說我們只能把任務交給這個線程去做,但是做了之后有沒有成功,線程是否異常我們都是不知道的,于是才有了Callable接口,這個接口就是對Runnable接口的一個補充,這個接口的實現類中沒有run()方法,卻有一個call()方法用于執行我們的任務邏輯,而且還能有返回值,并且能拋出異常等

順便一提,返回值已經被封裝成一個Future<T>類型的了,我們只需要從這個Futrue中取到返回值就可以進行后續操作了,有興趣的可以看看Futrue這個包裝類中有哪些方法可以試試,反正我暫時是沒什么興趣的。。。。

4.多線程下的jvm內存結構

初學者學多線程其實最迷糊的一點就是多線程的程序中,jvm是什么樣的啊?還是向以前那樣分嗎?到底多線程這個東西在jvm中是怎么樣存在的呢?下面我們就來簡單看看;

我自己總結的一句話:一個線程一個棧,一個方法一個幀;

這句話的意思就是每創建一個線程就會創建一個棧,每調用一個方法就會在棧中壓入一個棧幀;

其實java棧是一個動態的東西,不像我們前面看jvm內存結構就是一大塊java棧,里面可以有很多塊,一個線程一塊,總共合起來叫做java棧,我繼續來畫一個丑陋的圖看一看:

其實可以看到在我們java程序中用多線程的話,那么每一個線程都會創建一個棧,同時每個線程都有自己的PC計數器,而且每個棧都是該線程私有的,別的線程不能訪問;但是在java堆和方法區中的數據,是所有線程共享的,由于所有的線程都能夠使用共享區的數據,假設一個線程拿到堆中的一個A對象進行修改但是需要的時間比較長,此時另一個線程也要拿到A對象進行判斷然后做一些操作,這個時候就會出問題,因為前一個線程修改的數據還沒有同步過來,后面線程拿到的是舊數據,這個問題就是多線程的同步問題,后面我們慢慢分析;

5.總結

其實初學者覺得多線程比較難,主要是因為不理解多線程到底是什么?我們可以把多線程代碼用這種奇葩的形式看是不是明顯多了,其中主線程最開始執行并創建自己的棧和PC計數器,一直到創建其他的三個線程并把分別調用start()方法的時候,這些線程會隨機由CPU執行以及切換線程,并且各個線程都會創建自己的棧和PC計數器;而堆和方法區的數據是共享的,這會導致出現線程同步問題;

注意:千萬不要覺得主線程比其他創建的線程要特殊,除了我們程序是由主線程開始之外,這些線程都是出于同一地位,很有可能首先是主線程執行完畢,然后再執行1、2、3這三個線程哦~~

上述內容就是java虛擬機中多線程是怎樣總結的,你們學到知識或技能了嗎?如果還想學到更多技能或者豐富自己的知識儲備,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

北宁市| 慈利县| 甘谷县| 封丘县| 福建省| 卫辉市| 定西市| 贵德县| 临邑县| 镶黄旗| 北碚区| 依兰县| 开封县| 阜南县| 琼中| 调兵山市| 竹溪县| 都匀市| 斗六市| 辛集市| 孝义市| 阿尔山市| 讷河市| 道真| 德昌县| 和硕县| 新宁县| 龙江县| 和政县| 全南县| 行唐县| 韶山市| 双城市| 枝江市| 大厂| 漠河县| 平南县| 牙克石市| 新乡市| 西安市| 屯留县|