摘要:多線程基礎(chǔ)基本概念進(jìn)程所謂進(jìn)程就是運(yùn)行在操作系統(tǒng)的一個(gè)任務(wù),進(jìn)程是計(jì)算機(jī)任務(wù)調(diào)度的一個(gè)單位,操作系統(tǒng)在啟動(dòng)一個(gè)程序的時(shí)候,會(huì)為其創(chuàng)建一個(gè)進(jìn)程,就是一個(gè)進(jìn)程。代碼就不做過多解釋了,沒有代碼搞個(gè)毛的多線程。運(yùn)行狀態(tài)拿到的線程開始執(zhí)行。
多線程基礎(chǔ) 基本概念 進(jìn)程
所謂進(jìn)程就是運(yùn)行在操作系統(tǒng)的一個(gè)任務(wù),進(jìn)程是計(jì)算機(jī)任務(wù)調(diào)度的一個(gè)單位,操作系統(tǒng)在啟動(dòng)一個(gè)程序的時(shí)候,會(huì)為其創(chuàng)建一個(gè)進(jìn)程,JVM就是一個(gè)進(jìn)程。進(jìn)程與進(jìn)程之間是相互隔離的,每個(gè)進(jìn)程都有獨(dú)立的內(nèi)存空間。
計(jì)算機(jī)實(shí)現(xiàn)并發(fā)的原理是:CPU分時(shí)間片,交替執(zhí)行,宏觀并行,微觀串行。同理,在進(jìn)程的基礎(chǔ)上分出更小的任務(wù)調(diào)度單元就是線程,我們所謂的多線程就是一個(gè)進(jìn)程并發(fā)多個(gè)線程。
線程在上面我們提到,一個(gè)進(jìn)程可以并發(fā)出多個(gè)線程,而線程就是最小的任務(wù)執(zhí)行單元,具體來說,一個(gè)程序順序執(zhí)行的流程就是一個(gè)線程,我們常見的main就是一個(gè)線程(主線程)。
想要擁有一個(gè)線程,有這樣的一些不可或缺的部分,主要有:CPU時(shí)間片,數(shù)據(jù)存儲(chǔ)空間,代碼。
CPU時(shí)間片都是有操作系統(tǒng)進(jìn)行分配的,數(shù)據(jù)存儲(chǔ)空間就是我們常說的堆空間和??臻g,在線程之間,堆空間是多線程共享的,棧空間是互相獨(dú)立的,這樣做的好處不僅在于方便,也減少了很多資源的浪費(fèi)。代碼就不做過多解釋了,沒有代碼搞個(gè)毛的多線程。
繼承Thread類,覆蓋run方法
實(shí)現(xiàn)Runnable接口,覆蓋run方法
Runnable并不是線程對象,而是一個(gè)任務(wù)對象。那么Runnable和Thread有什么樣的關(guān)系呢?通過查閱API,我們發(fā)現(xiàn)創(chuàng)建一個(gè)線程除了使用Thread的無參構(gòu)造方法以外有一個(gè)有參構(gòu)造方法是這樣 :Thread(Runnable?target),通過這個(gè)方法會(huì)分配一個(gè)新的Thread 對象。
其中的參數(shù)是一個(gè)類型為Runnable的target屬性。
Runnable接口最大的作用就是為非Thread子類的類提供了一種實(shí)現(xiàn)線程的方式,只需要實(shí)現(xiàn)Runnable接口就可以借助Thread創(chuàng)建一個(gè)線程;另一方面,如果只想重寫run方法,不想得到其他的Thread的方法,實(shí)現(xiàn)Runnable是一個(gè)好的選擇。
線程池
ExecutorService(線程池 interface)
//通過工具類中的方法能夠新建一個(gè)線程池,用ExecutorService接受 ExecutorService es = Executors.newFixedThreadPool(2);
Callable對象
類似于Runnable(描述任務(wù)的interface)。
//創(chuàng)建一個(gè)Callable的實(shí)現(xiàn)類 Callabletask1 = new Callable (){ public Integer call() throws Exception{ int result = 0; for(int i=2;i<=100;i+=2){ result += i; Thread.sleep; } return result; } } //用Future對象接收fask1的返回值 將任務(wù)提交給線程池 Future f = es.submit(task1); //通過get方法獲取Future中的值 在這個(gè)時(shí)候主線程主動(dòng)的調(diào)取get 如果分支線程還沒有結(jié)束,主線程會(huì)在這里阻塞 int result = f1.get(); //關(guān)閉線程池 es.shutdown();
從以上這段代碼我們可以看到很多不一樣的地方,首先在Callable對象中是可以拋出異常的,其次有返回值,在這個(gè)基礎(chǔ)上也就引出了一個(gè)新的問題,如果接收該線程的對象?JDK1.5中也給出了解決的方法是Future對象.
啟動(dòng)線程
在這里我們需要明白,上面兩種方式并不會(huì)讓我們得到真正的線程,只是得到了線程對象,只有啟動(dòng)線程,才算得到了真正的線程。
通過執(zhí)行start()方法能夠啟動(dòng)一個(gè)線程,但是啟動(dòng)線程并不是立即執(zhí)行,成功啟動(dòng)的線程會(huì)處于就緒狀態(tài),什么時(shí)候執(zhí)行需要等到拿到時(shí)間片之后。
用戶線程和守護(hù)(Daemon)線程。
守護(hù)線程:守護(hù)線程會(huì)一直運(yùn)行,直到其他非守護(hù)線程都結(jié)束的時(shí)候,才會(huì)結(jié)束。有一個(gè)典型的守護(hù)線程就是:垃圾回收線程,和虛擬機(jī)共存亡,直到虛擬機(jī)中沒有任何線程的時(shí)候虛擬機(jī)關(guān)閉的時(shí)候才會(huì)終止,簡單說就是虛擬機(jī)在,它就在,虛擬機(jī)亡便亡。
線程的狀態(tài)上面我們提到過,一個(gè)線程在啟動(dòng)之后不會(huì)立馬執(zhí)行,而是處于就緒狀態(tài)(Ready),就緒狀態(tài)就是線程的狀態(tài)的一種,處于這種狀態(tài)的線程意味著一切準(zhǔn)備就緒, 需要等待系統(tǒng)分配到時(shí)間片。為什么沒有立馬運(yùn)行呢,因?yàn)橥粫r(shí)間只有一個(gè)線程能夠拿到時(shí)間片運(yùn)行,新線程啟動(dòng)的時(shí)候讓它啟動(dòng)的線程(主線程)正在運(yùn)行,只有等主線程結(jié)束,它才有機(jī)會(huì)拿到時(shí)間片運(yùn)行。
線程的狀態(tài):初始狀態(tài)(New),就緒狀態(tài)(Ready),運(yùn)行狀態(tài)(Running)(特別說明:在語法的定義中,就緒狀態(tài)和運(yùn)行狀態(tài)是一個(gè)狀態(tài)Runable),等待狀態(tài)(Waitering),終止?fàn)顟B(tài)(Terminated)
RUNNABLE),等待狀態(tài)(Waitering),終止?fàn)顟B(tài)(Terminated)
線程對象被創(chuàng)建出來,便是初始狀態(tài),這時(shí)候線程對象只是一個(gè)普通的對象,并不是一個(gè)線程。
就緒狀態(tài)(Ready):執(zhí)行start方法之后,進(jìn)入就緒狀態(tài),等待被分配到時(shí)間片。
運(yùn)行狀態(tài)(Running):拿到CPU的線程開始執(zhí)行。處于運(yùn)行時(shí)間的線程并不是永久的持有CPU直到運(yùn)行結(jié)束,很可能沒有執(zhí)行完畢時(shí)間片到期,就被收回CPU的使用權(quán)了,之后將會(huì)處于等待狀態(tài)。
等待狀態(tài)分為有限期等待和無限期等待,所謂有限期等待是線程使用sleep方法主動(dòng)進(jìn)入休眠,有一定的時(shí)間限制,時(shí)間到期就重新進(jìn)入就緒狀態(tài),再次等待被CPU選中。
而無限期等待就有些不同了,無限期并不是指永遠(yuǎn)的等待下去,而是指沒有時(shí)間限制,可能等待一秒也可能很多秒。至于進(jìn)入等待的原因也不盡相同,可能是因?yàn)镃PU時(shí)間片到期,也可能是因?yàn)橐粋€(gè)比較耗時(shí)的操作(數(shù)據(jù)庫),或者主動(dòng)的調(diào)用join方法。
wait和sleep的區(qū)別
wait | sleep |
---|---|
wait()方法是Object類里的方法 | sleep()是Thread類的static(靜態(tài))的方法 |
wait()睡眠時(shí),釋放對象鎖 | sleep()睡眠時(shí),保持對象鎖,仍然占有該鎖 |
常用于線程間通信 | 常用于暫停執(zhí)行 |
wait和notify/notifyAll是成對出現(xiàn)的, 必須在synchronize塊中被調(diào)用 |
在我看來,阻塞狀態(tài)實(shí)際上是一種比較特殊的等待狀態(tài),處于其他等待狀態(tài)的線程是在等著別的線程執(zhí)行結(jié)束,等著拿CPU的使用權(quán);而處于阻塞狀態(tài)的線程等待的不僅僅是CPU的使用權(quán),主要是鎖標(biāo)記,沒有拿到鎖標(biāo)記,即便是CPU有空也沒有辦法執(zhí)行。(關(guān)于鎖見下節(jié):線程同步)
等待和阻塞的區(qū)別
等待 | 阻塞 |
---|---|
已經(jīng)拿到鎖對象,或者說不存在拿不到執(zhí)行不了的情況 | 等待拿到鎖對象 |
等待被喚醒 | 等待拿到鎖對象 |
已經(jīng)終止的線程會(huì)處于該種狀態(tài)。
總結(jié)總體上來說,作為一個(gè)線程挺倒霉的,首先,不會(huì)知道自己什么時(shí)候被選中;其次在執(zhí)行過程中隨時(shí)可能被打斷讓出CPU,最后碰到數(shù)據(jù)庫等耗時(shí)的操作也要讓出CPU去等待,并且就算數(shù)據(jù)準(zhǔn)備好了, 仍然需要等著被挑選。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/70848.html
摘要:基礎(chǔ)知識復(fù)習(xí)后端掘金的作用表示靜態(tài)修飾符,使用修飾的變量,在中分配內(nèi)存后一直存在,直到程序退出才釋放空間。將對象編碼為字節(jié)流稱之為序列化,反之將字節(jié)流重建成對象稱之為反序列化。 Java 學(xué)習(xí)過程|完整思維導(dǎo)圖 - 后端 - 掘金JVM 1. 內(nèi)存模型( 內(nèi)存分為幾部分? 堆溢出、棧溢出原因及實(shí)例?線上如何排查?) 2. 類加載機(jī)制 3. 垃圾回收 Java基礎(chǔ) 什么是接口?什么是抽象...
摘要:哪吒社區(qū)技能樹打卡打卡貼函數(shù)式接口簡介領(lǐng)域優(yōu)質(zhì)創(chuàng)作者哪吒公眾號作者架構(gòu)師奮斗者掃描主頁左側(cè)二維碼,加入群聊,一起學(xué)習(xí)一起進(jìn)步歡迎點(diǎn)贊收藏留言前情提要無意間聽到領(lǐng)導(dǎo)們的談話,現(xiàn)在公司的現(xiàn)狀是碼農(nóng)太多,但能獨(dú)立帶隊(duì)的人太少,簡而言之,不缺干 ? 哪吒社區(qū)Java技能樹打卡?【打卡貼 day2...
摘要:線程可以被稱為輕量級進(jìn)程。一個(gè)守護(hù)線程是在后臺(tái)執(zhí)行并且不會(huì)阻止終止的線程。其他的線程狀態(tài)還有,和。上下文切換是多任務(wù)操作系統(tǒng)和多線程環(huán)境的基本特征。在的線程中并沒有可供任何對象使用的鎖和同步器。 原文:Java Multi-Threading and Concurrency Interview Questions with Answers 翻譯:并發(fā)編程網(wǎng) - 鄭旭東 校對:方騰飛 多...
摘要:多線程和并發(fā)問題是技術(shù)面試中面試官比較喜歡問的問題之一。線程可以被稱為輕量級進(jìn)程。一個(gè)守護(hù)線程是在后臺(tái)執(zhí)行并且不會(huì)阻止終止的線程。其他的線程狀態(tài)還有,和。上下文切換是多任務(wù)操作系統(tǒng)和多線程環(huán)境的基本特征。 多線程和并發(fā)問題是 Java 技術(shù)面試中面試官比較喜歡問的問題之一。在這里,從面試的角度列出了大部分重要的問題,但是你仍然應(yīng)該牢固的掌握J(rèn)ava多線程基礎(chǔ)知識來對應(yīng)日后碰到的問題。(...
摘要:在這個(gè)范圍廣大的并發(fā)技術(shù)領(lǐng)域當(dāng)中多線程編程可以說是基礎(chǔ)和核心,大多數(shù)抽象并發(fā)問題的構(gòu)思與解決都是基于多線程模型來進(jìn)行的。一般來說,多線程程序會(huì)面臨三類問題正確性問題效率問題死鎖問題。 多線程編程或者說范圍更大的并發(fā)編程是一種非常復(fù)雜且容易出錯(cuò)的編程方式,但是我們?yōu)槭裁催€要冒著風(fēng)險(xiǎn)艱辛地學(xué)習(xí)各種多線程編程技術(shù)、解決各種并發(fā)問題呢? 因?yàn)椴l(fā)是整個(gè)分布式集群的基礎(chǔ),通過分布式集群不僅可以大...
閱讀 1548·2021-11-24 09:39
閱讀 3758·2021-11-24 09:39
閱讀 1941·2021-11-16 11:54
閱讀 1541·2021-09-30 09:47
閱讀 1820·2021-09-26 10:16
閱讀 2399·2021-09-22 15:33
閱讀 1531·2021-09-14 18:01
閱讀 2530·2021-09-07 09:59