并發(fā)編程技術(shù)一之了解線程

了解線程由來

單核CPU之所以能夠?qū)崿F(xiàn)多進(jìn)程,主要是依賴操作系統(tǒng)的進(jìn)程調(diào)度算法。如時(shí)間片輪轉(zhuǎn)算法,可以實(shí)現(xiàn)QQ、微信、瀏覽器同時(shí)運(yùn)行,從而實(shí)現(xiàn)多進(jìn)程。

隨著計(jì)算機(jī)技術(shù)的發(fā)展,進(jìn)程出現(xiàn)很多弊端,一是由于進(jìn)程是資源擁有者,創(chuàng)建、撤消與切換存在較大的時(shí)空開銷,因此需要引入輕量進(jìn)程; 二是由于對(duì)稱多處理機(jī)出現(xiàn),可以滿足多個(gè)運(yùn)行單位,而多個(gè)進(jìn)程并行開銷過大。

因此在80年代,出現(xiàn)了能獨(dú)立運(yùn)行的基本單位 --- 線程。

從單核到多核

最初計(jì)算機(jī)是單任務(wù)的,然后發(fā)展到多任務(wù),接著出現(xiàn)多線程并行,同時(shí)計(jì)算機(jī)也從單cpu進(jìn)入到多cpu。如下圖

多任務(wù):其實(shí)就是利用操作系統(tǒng)時(shí)間片輪轉(zhuǎn)使用的原理。操作系統(tǒng)通過將cpu的執(zhí)行時(shí)間分割成多個(gè)時(shí)間片,為每個(gè)任務(wù)分配時(shí)間片,因?yàn)閏pu處理速度很快,這樣就用戶看來好像每個(gè)任務(wù)都在同時(shí)執(zhí)行,感覺有多個(gè)cpu,但本質(zhì)上一個(gè)時(shí)間點(diǎn)只有一個(gè)任務(wù)在運(yùn)行。

為什么會(huì)有線程?

線程切換比進(jìn)程切換速度會(huì)快

在什么場(chǎng)景下使用多線程?

通過并行計(jì)算提高程序性能

等待網(wǎng)絡(luò)、IO響應(yīng)導(dǎo)致的耗時(shí)時(shí)間問題

線程的分類有哪些?

用戶線程、內(nèi)核線程、混合式

進(jìn)程和線程的關(guān)系?

根本區(qū)別:進(jìn)程是資源分配的最小單位,線程是CPU調(diào)度的最小單位

進(jìn)程是一個(gè)應(yīng)用程序在處理機(jī)上的一次執(zhí)行過程,它是一個(gè)動(dòng)態(tài)概念,而線程是進(jìn)程中的一部分,進(jìn)程包含多個(gè)線程在運(yùn)行。

開銷:每個(gè)進(jìn)程都有獨(dú)立的代碼和數(shù)據(jù)空間,程序之間的切換會(huì)有較大的開銷;線程可以看做輕量級(jí)的進(jìn)程,同一類線程共享代碼和數(shù)據(jù)空間,每個(gè)線程都有自己獨(dú)立的運(yùn)行棧和程序計(jì)數(shù)器,線程之間切換的開銷小。

內(nèi)存分配:系統(tǒng)在運(yùn)行的時(shí)候會(huì)為每個(gè)進(jìn)程分配不同的內(nèi)存空間,則線程除了CPU之外,系統(tǒng)不會(huì)為線程分配內(nèi)存,線程組之是只能共享資源。

線程的實(shí)現(xiàn)方法有哪些

Thread、Runnable、Callable/future

線程的狀態(tài)有哪些

NEW 新建

READY 就緒

RUNNABLE 運(yùn)行

BLOCKED 阻塞

? 等待阻塞 wait

? 同步阻塞 ?synchronized

? 其他阻塞 sleep/join

WAITING 等待

TIMED_WAITING 超時(shí)等待

TERMINATED 終止

線程狀態(tài)圖如下:

?查看線程狀態(tài)的代碼如下:

public class ThreadStatusDemo {

? ?public static void main(String[] args) {

? ? ? ?new Thread(()->{

? ? ? ? ? ?while (true){

? ? ? ? ? ? ? ?try {

? ? ? ? ? ? ? ? ? ?TimeUnit.SECONDS.sleep(100);

? ? ? ? ? ? ? ?} catch (InterruptedException e) {

? ? ? ? ? ? ? ? ? ?e.printStackTrace();

? ? ? ? ? ? ? ?}

? ? ? ? ? ?}

? ? ? ?},"timewaiting").start();

? ? ? ?new Thread(()->{

? ? ? ? ? while (true){

? ? ? ? ? ? ? synchronized (ThreadStatusDemo.class){

? ? ? ? ? ? ? ? ? try {

? ? ? ? ? ? ? ? ? ? ? ThreadStatusDemo.class.wait();

? ? ? ? ? ? ? ? ? } catch (InterruptedException e) {

? ? ? ? ? ? ? ? ? ? ? e.printStackTrace();

? ? ? ? ? ? ? ? ? }

? ? ? ? ? ? ? }

? ? ? ? ? }

? ? ? ?},"waiting").start();

? ? ? ?new Thread(new BlockDemo(),"BlockDemo-0").start();

? ? ? ?new Thread(new BlockDemo(),"BlockDemo-1").start();

? ?}

? ?static ?class ?BlockDemo extends ?Thread{

? ? ? ?@Override

? ? ? ?public void run() {

? ? ? ? ? ?synchronized ( BlockDemo.class){

? ? ? ? ? ? ? ?try {

? ? ? ? ? ? ? ? ? ?TimeUnit.SECONDS.sleep(100);

? ? ? ? ? ? ? ?} catch (InterruptedException e) {

? ? ? ? ? ? ? ? ? ?e.printStackTrace();

? ? ? ? ? ? ? ?}

? ? ? ? ? ?}

? ? ? ?}

? ?}

}

結(jié)果

E:\lession\target\classes\com\example\lession\thread>jstack 8712

2019-01-20 15:16:20

Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.144-b01 mixed mode):

"DestroyJavaVM" #17 prio=5 os_prio=0 tid=0x00000000025ea000 nid=0xce0 waiting on condition [0x0000000000000000]

? java.lang.Thread.State: RUNNABLE

"BlockDemo-1" #16 prio=5 os_prio=0 tid=0x0000000059c5c800 nid=0x27a8 waiting for monitor entry [0x000000005a5af000]

? java.lang.Thread.State: BLOCKED (on object monitor)

? ? ? ?at com.example.lession.thread.ThreadStatusDemo$BlockDemo.run(ThreadStatusDemo.java:42)

? ? ? ?- waiting to lock <0x00000000d82d41f0> (a java.lang.Class for com.example.lession.thread.ThreadStatusDemo$BlockDemo)

? ? ? ?at java.lang.Thread.run(Thread.java:748)

"BlockDemo-0" #14 prio=5 os_prio=0 tid=0x0000000059c5a000 nid=0xd50 waiting on condition [0x00000000598ff000]

? java.lang.Thread.State: TIMED_WAITING (sleeping)

? ? ? ?at java.lang.Thread.sleep(Native Method)

? ? ? ?at java.lang.Thread.sleep(Thread.java:340)

? ? ? ?at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)

? ? ? ?at com.example.lession.thread.ThreadStatusDemo$BlockDemo.run(ThreadStatusDemo.java:42)

? ? ? ?- locked <0x00000000d82d41f0> (a java.lang.Class for com.example.lession.thread.ThreadStatusDemo$BlockDemo)

? ? ? ?at java.lang.Thread.run(Thread.java:748)

"waiting" #12 prio=5 os_prio=0 tid=0x0000000059c59000 nid=0x24b4 in Object.wait() [0x000000005a49f000]

? java.lang.Thread.State: WAITING (on object monitor)

? ? ? ?at java.lang.Object.wait(Native Method)

? ? ? ?- waiting on <0x00000000d7fc0708> (a java.lang.Class for com.example.lession.thread.ThreadStatusDemo)

? ? ? ?at java.lang.Object.wait(Object.java:502)

? ? ? ?at com.example.lession.thread.ThreadStatusDemo.lambda$main$1(ThreadStatusDemo.java:23)

? ? ? ?- locked <0x00000000d7fc0708> (a java.lang.Class for com.example.lession.thread.ThreadStatusDemo)

? ? ? ?at com.example.lession.thread.ThreadStatusDemo$$Lambda$2/443308702.run(Unknown Source)

? ? ? ?at java.lang.Thread.run(Thread.java:748)

"timewaiting" #11 prio=5 os_prio=0 tid=0x0000000059c55800 nid=0x10d8 waiting on condition [0x000000005a37e000]

? java.lang.Thread.State: TIMED_WAITING (sleeping)

? ? ? ?at java.lang.Thread.sleep(Native Method)

? ? ? ?at java.lang.Thread.sleep(Thread.java:340)

? ? ? ?at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)

? ? ? ?at com.example.lession.thread.ThreadStatusDemo.lambda$main$0(ThreadStatusDemo.java:12)

? ? ? ?at com.example.lession.thread.ThreadStatusDemo$$Lambda$1/205797316.run(Unknown Source)

? ? ? ?at java.lang.Thread.run(Thread.java:748)

"Service Thread" #10 daemon prio=9 os_prio=0 tid=0x0000000058c0a000 nid=0x2134 runnable [0x0000000000000000]

? java.lang.Thread.State: RUNNABLE

"C1 CompilerThread2" #9 daemon prio=9 os_prio=2 tid=0x0000000058b68000 nid=0x1ea4 waiting on condition [0x0000000000000000]

? java.lang.Thread.State: RUNNABLE

"C2 CompilerThread1" #8 daemon prio=9 os_prio=2 tid=0x0000000058b5f800 nid=0x1fac waiting on condition [0x0000000000000000]

? java.lang.Thread.State: RUNNABLE

"C2 CompilerThread0" #7 daemon prio=9 os_prio=2 tid=0x0000000058b5e800 nid=0x2090 waiting on condition [0x0000000000000000]

? java.lang.Thread.State: RUNNABLE

"Monitor Ctrl-Break" #6 daemon prio=5 os_prio=0 tid=0x0000000058b5c000 nid=0x2470 runnable [0x00000000591cf000]

? java.lang.Thread.State: RUNNABLE

? ? ? ?at java.net.SocketInputStream.socketRead0(Native Method)

? ? ? ?at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)

? ? ? ?at java.net.SocketInputStream.read(SocketInputStream.java:171)

? ? ? ?at java.net.SocketInputStream.read(SocketInputStream.java:141)

? ? ? ?at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)

? ? ? ?at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)

? ? ? ?at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)

? ? ? ?- locked <0x00000000d8030d18> (a java.io.InputStreamReader)

? ? ? ?at java.io.InputStreamReader.read(InputStreamReader.java:184)

? ? ? ?at java.io.BufferedReader.fill(BufferedReader.java:161)

? ? ? ?at java.io.BufferedReader.readLine(BufferedReader.java:324)

? ? ? ?- locked <0x00000000d8030d18> (a java.io.InputStreamReader)

? ? ? ?at java.io.BufferedReader.readLine(BufferedReader.java:389)

? ? ? ?at com.intellij.rt.execution.application.AppMainV2$1.run(AppMainV2.java:64)

"Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x00000000588fc000 nid=0x274c waiting on condition [0x0000000000000000]

? java.lang.Thread.State: RUNNABLE

"Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x000000005747f000 nid=0x1c88 runnable [0x0000000000000000]

? java.lang.Thread.State: RUNNABLE

"Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000000005745c800 nid=0x20c4 in Object.wait() [0x00000000588de000]

? java.lang.Thread.State: WAITING (on object monitor)

? ? ? ?at java.lang.Object.wait(Native Method)

? ? ? ?- waiting on <0x00000000d7d88ec8> (a java.lang.ref.ReferenceQueue$Lock)

? ? ? ?at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143)

? ? ? ?- locked <0x00000000d7d88ec8> (a java.lang.ref.ReferenceQueue$Lock)

? ? ? ?at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:164)

? ? ? ?at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:209)

"Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x0000000057415800 nid=0x16e4 in Object.wait() [0x00000000587ce000]

? java.lang.Thread.State: WAITING (on object monitor)

? ? ? ?at java.lang.Object.wait(Native Method)

? ? ? ?- waiting on <0x00000000d7d86b68> (a java.lang.ref.Reference$Lock)

? ? ? ?at java.lang.Object.wait(Object.java:502)

? ? ? ?at java.lang.ref.Reference.tryHandlePending(Reference.java:191)

? ? ? ?- locked <0x00000000d7d86b68> (a java.lang.ref.Reference$Lock)

? ? ? ?at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153)

"VM Thread" os_prio=2 tid=0x000000005740e000 nid=0x19d0 runnable

"GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00000000025ff800 nid=0x638 runnable

"GC task thread#1 (ParallelGC)" os_prio=0 tid=0x0000000002601000 nid=0x3a8 runnable

"GC task thread#2 (ParallelGC)" os_prio=0 tid=0x0000000002602800 nid=0x1ca4 runnable

"GC task thread#3 (ParallelGC)" os_prio=0 tid=0x0000000002604800 nid=0x2130 runnable

"VM Periodic Task Thread" os_prio=2 tid=0x0000000058c65800 nid=0x1e44 waiting on condition

JNI global references: 336

------------

再次感謝您已看完全文,歡迎關(guān)注微信公眾號(hào)`猿碼` ,您的關(guān)注我會(huì)持續(xù)更新文章!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容