日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

java厨房_Java多线程基础

發(fā)布時間:2023/12/15 java 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 java厨房_Java多线程基础 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

目錄:

進程和線程

為什么使用多線程?

多線程的創(chuàng)建方式

Runnable與Thread兩種方式比較

start()與run()方法

線程的生命周期/狀態(tài)轉(zhuǎn)換

常用方法使用與解讀

線程的優(yōu)先級

守護線程

1、進程和線程

進程(Process)是計算機中的程序關(guān)于某數(shù)據(jù)集合上的一次運行活動,是系統(tǒng)進行資源分配和調(diào)度的基本單位,是操作系統(tǒng)結(jié)構(gòu)的基礎(chǔ)。在早期面向進程設計的計算機結(jié)構(gòu)中,進程是程序的基本執(zhí)行實體;在當代面向線程設計的計算機結(jié)構(gòu)中,進程是線程的容器。程序是指令、數(shù)據(jù)及其組織形式的描述,進程是程序的實體。

一個程序就是一個進程,而一個程序中的多個任務則被稱為線程。

進程是表示資源分配的基本單位,線程是進程中執(zhí)行運算的最小單位,亦是調(diào)度運行的基本單位。

2、為什么要使用多線程?

提升效率,提升性能;發(fā)揮多核CPU的優(yōu)勢。

防止阻塞:從程序運行效率的角度來看,單核CPU不但不會發(fā)揮出多線程的優(yōu)勢,反而會因為在單核CPU上運行多線程導致線程上下文的切換,而降低程序整體的效率。但是單核CPU我們還是要應用多線程,就是為了防止阻塞。試想,如果單核CPU使用單線程,那么只要這個線程阻塞了,比方說遠程讀取某個數(shù)據(jù)吧,對端遲遲未返回又沒有設置超時時間,那么你的整個程序在數(shù)據(jù)返回回來之前就停止運行了。多線程可以防止這個問題,多條線程同時運行,哪怕一條線程的代碼執(zhí)行讀取數(shù)據(jù)阻塞,也不會影響其它任務的執(zhí)行。

3、多線程的創(chuàng)建方式[細分為5種]

繼承Thread類,重寫run方法。new一個實例。

實現(xiàn)Runnable接口,重寫run方法。作為參數(shù)傳入Thread thread = new Thread(參數(shù));來創(chuàng)建。

匿名內(nèi)部類的方式(與實現(xiàn)Runnable接口一樣,只是形式不同 )

通過并發(fā)包中Callable、Callback來創(chuàng)建

通過線程池來創(chuàng)建線程

4、Runnable與Thread兩種方式比較

繼承Thread不必多說,繼承后重寫run方法。new一個實例調(diào)用start()方法就可以了。

兩者非要比較的話,使用Runnable較好,因為實現(xiàn)接口的方式比繼承類的方式更靈活,也能減少程序之間的耦合度,面向接口編程也是設計模式6大原則的核心。

這里重點看下實現(xiàn)Runnable接口創(chuàng)建線程,實現(xiàn)Runnable接口實際上還是需要Thread類來創(chuàng)建線程,我們來看下Thread的構(gòu)造方法API:

另外需要說明的是Thread.java類也實現(xiàn)了Runnable接口,如下圖:

那也就意味著Thread的構(gòu)造函數(shù)不僅可以傳入Runnable接口的對象還可以傳入一個Thread類的對象,這樣就可以將一個Thread類的run()方法交由其他線程來調(diào)用。

5、start()與run()方法

只有調(diào)用了start()方法,才會表現(xiàn)出多線程的特性,不同線程的run()方法里面的代碼交替執(zhí)行。如果只是調(diào)用run()方法,那么代碼還是同步執(zhí)行的,必須等待一個線程的run()方法里面的代碼全部執(zhí)行完畢之后,另外一個線程才可以執(zhí)行其run()方法里面的代碼。

6、線程的生命周期/狀態(tài)轉(zhuǎn)換

生命周期的五種狀態(tài)【簡單版文字描述】:

新建(new Thread)當創(chuàng)建Thread類的一個實例(對象)時,此線程進入新建狀態(tài)(未被啟動)。

例如:Thread t1=new Thread();

就緒(runnable)線程已經(jīng)被啟動,正在等待被分配給CPU時間片,也就是說此時線程正在就緒隊列中排隊等候得到CPU資源。例如:t1.start();

運行(running)線程獲得CPU資源正在執(zhí)行任務(run()方法),此時除非此線程自動放棄CPU資源或者有優(yōu)先級更高的線程進入,線程將一直運行到結(jié)束。

死亡(dead)

當線程執(zhí)行完畢或被其它線程殺死,線程就進入死亡狀態(tài),這時線程不可能再進入就緒狀態(tài)等待執(zhí)行。

自然終止:正常運行run()方法后終止

異常終止:調(diào)用stop()方法讓一個線程終止運行,這里說明下stop()方法雖然可以停止線程,但這個方法線程不安全,在新版本的java中已經(jīng)被廢棄。

堵塞(blocked)

由于某種原因?qū)е抡谶\行的線程讓出CPU并暫停自己的執(zhí)行,即進入堵塞狀態(tài)。

正在睡眠:用sleep(long t) 方法可使線程進入睡眠方式。一個睡眠著的線程在指定的時間過去可進入就緒狀態(tài)。

正在等待:調(diào)用wait()方法。(調(diào)用notify()方法回到就緒狀態(tài))

被另一個線程所阻塞:調(diào)用suspend()方法。(調(diào)用resume()方法恢復)廢棄

更全的線程狀態(tài)轉(zhuǎn)換圖如下:

7、常用方法使用與解讀

start():使線程進入“就緒”(可運行)狀態(tài),通知jvm開啟新線程來執(zhí)行run方法。如果多次調(diào)用了start()方法,則會出現(xiàn)Exception in thread "main" java.lang.IllegalThreadStateException因為start會修改當前線程的狀態(tài)變量,只有狀態(tài)變量是初始值時才能start。

線程中斷相關(guān):

stop()【廢棄】:停止一個線程,可以使用Thread.stop()方法,但是他是不安全的,而且已經(jīng)被廢棄了呢。調(diào)用的時候還會拋出一個java.lang.ThreadDeath異常 ,但是通常情況下,此異常不需要顯示的捕捉。廢棄原因:因為強制讓線程停止則有可能使一些請理性的工作得不到完成。另外情況就是對鎖定的對象進行了“解鎖”,導致 數(shù)據(jù)得不到同步的處理,出現(xiàn)數(shù)據(jù)不一致的問題。

interrupt():大多數(shù)停止一個線程的操作是使用Thread.interrupt()方法,盡管名義為“中止,停止”但這個方法不會終止一個正在運行的線程,只是打了一個標記,還需要加入一個判斷才可以完成線程的停止。Thread.java中提供了兩個方法:

this.interrupted():測試當前線程是否已經(jīng)中斷。public static boolean interrupted()

this.isInterrupted():測試線程是否已經(jīng)中斷。public boolean isInterrupted()

具體終止線程操作(來源網(wǎng)絡):https://www.cnblogs.com/jenkov/p/juc_interrupt.html

其中的return停止線程可以的,但是還是建議使用“拋異?!钡姆椒▉韺崿F(xiàn)線程的停止,因為在catch塊中還可以將異常上拋,使線程停止的事件得以傳播。

另外這兩個方法的區(qū)別:

interrupted()無論怎么都是指正在運行的線程。而isInterrupted()就是表示指定的線程咯。

interrupted()會清除標記,什么意思呢?就是調(diào)用interrupt()給當前線程打一個中斷標記,第一次用interrupted()會返回true但是 如果不處理,之后的調(diào)用都會返回false因為它把中斷標記給清了。

暫停線程相關(guān):

suspend()與resume()【廢棄】:一個暫停線程,一個恢復線程到運行狀態(tài)。suspend()會暫停線程,假如當前線程為關(guān)鍵數(shù)據(jù)結(jié)構(gòu)加鎖 這時被掛起那么鎖將無法釋放對其他線程來說造成死鎖。同時也會因為線程的暫停出現(xiàn)數(shù)據(jù)不同步的現(xiàn)象。

currentThread():該方法返回代碼段正在被那個線程調(diào)用的信息。

isAlive():判斷當前線程是否處于活動的狀態(tài)?;顒訝顟B(tài)是指線程已經(jīng)啟動尚未終止的狀態(tài)。線程處于正在運行或準備開始運行的狀態(tài),就認為線程是“存活”的。

sleep():在指定毫秒內(nèi)讓當前正在執(zhí)行的線程休眠。這個“正在執(zhí)行的線程”是指this.currentThread()返回的線程。

getId():取得線程的唯一標識。這個是自動分配的,且是唯一的。

yield():放棄當前的CUP資源,將它讓給其他的任務去占用CPU執(zhí)行時間。但是放棄的時間不確定,有可能剛剛放棄,馬上又獲得CPU時間片。

8、線程的優(yōu)先級

線程可以劃分優(yōu)先級,CPU優(yōu)先執(zhí)行優(yōu)先級較高的線程對象中的任務。

設置線程的優(yōu)先級使用setPriority()方法,該方法的源碼如下:

/**

* Changes the priority of this thread.

*

* First the checkAccess method of this thread is called

* with no arguments. This may result in throwing a

* SecurityException.

*

* Otherwise, the priority of this thread is set to the smaller of

* the specified newPriority and the maximum permitted

* priority of the thread's thread group.

*

* @param newPriority priority to set this thread to

* @exception IllegalArgumentException If the priority is not in the

* range MIN_PRIORITY to

* MAX_PRIORITY.

* @exception SecurityException if the current thread cannot modify

* this thread.

* @see #getPriority

* @see #checkAccess()

* @see #getThreadGroup()

* @see #MAX_PRIORITY

* @see #MIN_PRIORITY

* @see ThreadGroup#getMaxPriority()

*/

public final void setPriority(int newPriority) {

ThreadGroup g;

checkAccess();

if (newPriority > MAX_PRIORITY || newPriority < MIN_PRIORITY) {

throw new IllegalArgumentException();

}

if((g = getThreadGroup()) != null) {

if (newPriority > g.getMaxPriority()) {

newPriority = g.getMaxPriority();

}

setPriority0(priority = newPriority);

}

}

在Java中,線程的優(yōu)先級分為【1~10】10個等級,從代碼中我們也能看到,如果小于1或者大于10,則會拋出

IllegalArgumentException異常。

JDK中使用三個常量來預定義線程的優(yōu)先級:

/**

* The minimum priority that a thread can have.

*/

public final static int MIN_PRIORITY = 1;

/**

* The default priority that is assigned to a thread.

*/

public final static int NORM_PRIORITY = 5;

/**

* The maximum priority that a thread can have.

*/

public final static int MAX_PRIORITY = 10;

線程優(yōu)先級的特性:

繼承性:比如A線程啟動B線程,則B線程的優(yōu)先級與A是一樣的。設置A線程的優(yōu)先級為6那么B線程也就是6。

規(guī)則性:線程優(yōu)先級等級差距很大的時候,誰先執(zhí)行完與代碼的調(diào)用順序無關(guān)。CPU盡量將資源讓給優(yōu)先級比較高的線程

隨機性:優(yōu)先級高的線程不一定每次都先執(zhí)行完。優(yōu)先級相近越能看出隨機性。

優(yōu)先級高的代碼執(zhí)行速度更快?

這是一個相對的問題,因為優(yōu)先級高的會占用更多的時間片,相同的任務量能夠更早的完成。或者說相同時間內(nèi)可以完成更多的操作。但實際上CPU處理的速度是一樣的。

9、守護線程

守護線程是一種特殊的線程,任何一個守護線程都是整個(沒錯是整個)JVM中所有非守護線程的“保姆”,只要當前JVM實例中存在任何一個非守護線程沒有結(jié)束,守護線程就在工作,只有當最后一個非守護線程結(jié)束時,守護線程才能隨著JVM一同結(jié)束工作。Daemon的作用就是為其他線程的運行提供便利服務,守護線程最經(jīng)典的應用就是GC(垃圾回收器)。

讓一個線程成為守護線程的方法是setDaemon(true);

總結(jié)

以上是生活随笔為你收集整理的java厨房_Java多线程基础的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。