摘要:時(shí)間年月日星期六說(shuō)明本文部分內(nèi)容均來(lái)自慕課網(wǎng)。慕課網(wǎng)教學(xué)源碼無(wú)學(xué)習(xí)源碼第一章課前準(zhǔn)備前言課程說(shuō)明比較和這兩種線程創(chuàng)建的方式,需要知道和的基本創(chuàng)建方式。一旦主線程獲取到了用戶的輸入,這時(shí)候,阻塞就會(huì)解除掉,主線程繼續(xù)運(yùn)行,直到結(jié)束。
時(shí)間:2017年07月08日星期六
說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com
教學(xué)源碼:無(wú)
學(xué)習(xí)源碼:https://github.com/zccodere/s...
課程說(shuō)明
比較Thread和Runnable這兩種線程創(chuàng)建的方式,需要知道Thread和Runnable的基本創(chuàng)建方式。
課程目標(biāo)和學(xué)習(xí)內(nèi)容
線程創(chuàng)建的兩種方式比較 線程的生命周期 線程的守護(hù)神:守護(hù)線程第二章:Thread VS Runnable 2-1 回顧線程創(chuàng)建的兩種方式
方式一:繼承Thread類
方式二:實(shí)現(xiàn)Runnable接口
線程創(chuàng)建的兩種方式
2-2 應(yīng)用Thread模擬賣票兩種方式的比較
Runnable方式可以避免Thread方式由于Java單繼承特性帶來(lái)的缺陷 Runnable的代碼可以被多個(gè)線程(Thread實(shí)例)共享,適合于多個(gè)線程處理同一個(gè)資源的情況
案例:模擬買票
代碼演示
1.編寫(xiě)MyThread類
package com.myimooc.ticketsthread; /** * 使用 Thread 創(chuàng)建線程 * @author ZhangCheng on 2017-07-08 * */ public class MyThread extends Thread { /** 一共有5張火車票 */ private int ticketsCont = 5; /** 窗口,也即是線程的名字 */ private String name; public MyThread(String name){ this.name = name; } // 寫(xiě)買票邏輯 @Override public void run() { while(ticketsCont > 0 ){ // 如果還有票,就賣掉一張 ticketsCont--; System.out.println(name + "賣了1張票,剩余票數(shù)為:"+ticketsCont); } } }
2.編寫(xiě)TicketsThread類
package com.myimooc.ticketsthread; /** * 主類-啟動(dòng)線程類 * @author ZhangCheng on 2017-07-08 * */ public class TicketsThread { public static void main(String[] args) { // 創(chuàng)建三個(gè)線程,模擬三個(gè)窗口賣票 MyThread mt1 = new MyThread("窗口1"); MyThread mt2 = new MyThread("窗口2"); MyThread mt3 = new MyThread("窗口3"); // 啟動(dòng)這三個(gè)線程,即窗口開(kāi)始賣票 mt1.start(); mt2.start(); mt3.start(); } }
運(yùn)行結(jié)果
總共有5張票,但是三個(gè)窗口加在一起賣了15張票。造成有些人買了票,上不了車,這種情況不是我們?cè)敢饪吹降?。具體原因,寫(xiě)完Runnable后,會(huì)講解。
2-3 應(yīng)用Runnable模擬賣票代碼演示
1.編寫(xiě)MyThread類
package com.myimooc.ticketsrunnable; /** * 使用 Runnable 創(chuàng)建線程 * @author ZhangCheng on 2017-07-08 * */ public class MyThread implements Runnable { /** 一共有5張火車票 */ private int ticketsCont = 5; // 寫(xiě)買票邏輯 @Override public void run() { while(ticketsCont > 0 ){ // 如果還有票,就賣掉一張 ticketsCont--; System.out.println(Thread.currentThread().getName() + "賣了1張票,剩余票數(shù)為:"+ticketsCont); } } }
2.編寫(xiě)TicketsRunnable類
package com.myimooc.ticketsrunnable; /** * 主類-啟動(dòng)線程類 * @author ZhangCheng on 2017-07-08 * */ public class TicketsRunnable { public static void main(String[] args) { MyThread mt = new MyThread(); // 創(chuàng)建三個(gè)線程,模擬三個(gè)窗口賣票 Thread th1 = new Thread(mt,"窗口1"); Thread th2 = new Thread(mt,"窗口2"); Thread th3 = new Thread(mt,"窗口3"); // 啟動(dòng)這三個(gè)線程,即窗口開(kāi)始賣票 th1.start(); th2.start(); th3.start(); } }
運(yùn)行結(jié)果
2-4 應(yīng)用揭秘兩種方式的區(qū)別
第三章:線程的生命周期和守護(hù)線程 3-1 線程的生命周期線程的生命周期
創(chuàng)建
新建一個(gè)線程對(duì)象,如Threaf thd = new Thread()
就緒
創(chuàng)建了線程對(duì)象后,調(diào)用了線程的start()方法(注意:此時(shí)線程只是進(jìn)入了線程隊(duì)列,等待獲取CPU服務(wù),具備了運(yùn)行的條件,但并不一定已經(jīng)開(kāi)始運(yùn)行了)
運(yùn)行
處于就緒狀態(tài)的線程,一旦獲取了CPU資源,便進(jìn)入到運(yùn)行狀態(tài),開(kāi)始執(zhí)行run()方法里面的邏輯
終止
線程的run()方法執(zhí)行完畢,或者線程調(diào)用了stop()方法,線程便進(jìn)入終止?fàn)顟B(tài)
阻塞
一個(gè)正在執(zhí)行的線程在某些情況下,由于某種原因而暫時(shí)讓出了CPU資源,暫停了自己的執(zhí)行,便進(jìn)入了阻塞狀態(tài),如調(diào)用了sleep()方法
阻塞狀態(tài)示意圖
3-2 守護(hù)線程理論知識(shí)Java線程有兩類
用戶線程:運(yùn)行在前臺(tái),執(zhí)行具體的任務(wù) 程序的主線程、連接網(wǎng)絡(luò)的子線程等都是用戶線程 守護(hù)線程:運(yùn)行在后臺(tái),為其他前臺(tái)線程服務(wù) 特點(diǎn):一旦所有用戶線程都結(jié)束運(yùn)行,守護(hù)線程會(huì)隨JVM一起結(jié)束工作 應(yīng)用:數(shù)據(jù)庫(kù)連接池中的監(jiān)測(cè)線程、JVM虛擬機(jī)啟動(dòng)后的監(jiān)測(cè)線程 最常見(jiàn)的守護(hù)線程:垃圾回收線程
如何設(shè)置守護(hù)線程
可以通過(guò)調(diào)用Thread類的setDaemon(true)方法來(lái)設(shè)置當(dāng)前的線程為守護(hù)線程
注意事項(xiàng)
setDaemon(true)必須在start()方法之前調(diào)用,否則會(huì)拋出IllegalThreadStateException異常 在守護(hù)線程中產(chǎn)生的新線程也是守護(hù)線程 不是所有的任務(wù)都可以分配給守護(hù)線程來(lái)執(zhí)行,比如讀寫(xiě)操作或者計(jì)算邏輯3-3 守護(hù)線程代碼示例
模擬場(chǎng)景示意圖
模擬場(chǎng)景說(shuō)明
一共有兩個(gè)線程,一個(gè)主線程,一個(gè)守護(hù)線程。守護(hù)線程會(huì)在很長(zhǎng)的時(shí)間內(nèi)不停的往文件中寫(xiě)數(shù)據(jù),主線程會(huì)阻塞等待來(lái)自鍵盤(pán)的輸入。一旦主線程獲取到了用戶的輸入,這時(shí)候,阻塞就會(huì)解除掉,主線程繼續(xù)運(yùn)行,直到結(jié)束。而一旦主線程結(jié)束,用戶線程就沒(méi)有了。這時(shí)候即使數(shù)據(jù)還沒(méi)有寫(xiě)完,守護(hù)線程也會(huì)隨虛擬機(jī)一起結(jié)束運(yùn)行。
代碼演示
1.編寫(xiě)DaemonThread類
package com.myimooc.daemonthread; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStream; /** * 守護(hù)線程。使用 Runnable 創(chuàng)建線程 * @author ZhangCheng on 2017-07-08 * */ public class DaemonThread implements Runnable { @Override public void run() { System.out.println("進(jìn)入守護(hù)線程" + Thread.currentThread().getName()); try { writeToFile(); } catch (Exception e) { e.printStackTrace(); } System.out.println("退出守護(hù)線程" + Thread.currentThread().getName()); } private void writeToFile() throws Exception{ File fileName = new File("d:" + File.separator + "daemon.txt"); // 向文件中追加數(shù)據(jù) OutputStream os = new FileOutputStream(fileName,true); int count = 0; while(count < 999){ os.write((" word" + count).getBytes()); System.out.println("守護(hù)線程" + Thread.currentThread().getName() + "向文件中寫(xiě)入了word" + count); count++; // 線程休眠1秒 Thread.sleep(1000); } os.close(); } }
2.編寫(xiě)DaemonThreadDemo類
package com.myimooc.daemonthread; import java.util.Scanner; /** * 主線程 * @author ZhangCheng on 2017-07-08 * */ public class DaemonThreadDemo { public static void main(String[] args) { System.out.println("進(jìn)入主線程" + Thread.currentThread().getName()); DaemonThread daemonThread = new DaemonThread(); Thread thread = new Thread(daemonThread); thread.setDaemon(true); thread.start(); Scanner sc = new Scanner(System.in); sc.next(); sc.close(); System.out.println("退出主線程" + Thread.currentThread().getName()); } }3-4 使用jstack生成線程快照
常用查看線程工具
jstack
作用:生成JVM當(dāng)前時(shí)刻線程的快照(threaddump,即當(dāng)前進(jìn)程中所有線程的信息) 目的:幫助定位程序問(wèn)題出現(xiàn)的原因,如長(zhǎng)時(shí)間停頓、CPU占用率過(guò)高等
使用命令
jstack -l PID 生成線程快照
快照案例
2017-07-08 23:49:46 Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.101-b13 mixed mode): "Thread-0" #10 daemon prio=5 os_prio=0 tid=0x000000001d209800 nid=0x2e00 waiting on condition [0x000000001dd2f000] java.lang.Thread.State: TIMED_WAITING (sleeping) at java.lang.Thread.sleep(Native Method) at com.myimooc.daemonthread.DaemonThread.writeToFile(DaemonThread.java:39) at com.myimooc.daemonthread.DaemonThread.run(DaemonThread.java:19) at java.lang.Thread.run(Thread.java:745) Locked ownable synchronizers: - None "Service Thread" #9 daemon prio=9 os_prio=0 tid=0x000000001d1b9800 nid=0x2480 runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "C1 CompilerThread2" #8 daemon prio=9 os_prio=2 tid=0x000000001d13b000 nid=0x2078 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "C2 CompilerThread1" #7 daemon prio=9 os_prio=2 tid=0x000000001be2d800 nid=0x24f4 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "C2 CompilerThread0" #6 daemon prio=9 os_prio=2 tid=0x000000001bddf000 nid=0x2f64 waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "Attach Listener" #5 daemon prio=5 os_prio=2 tid=0x000000001bdde000 nid=0x1c1c waiting on condition [0x0000000000000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "Signal Dispatcher" #4 daemon prio=9 os_prio=2 tid=0x000000001bdc8800 nid=0x247c runnable [0x0000000000000000] java.lang.Thread.State: RUNNABLE Locked ownable synchronizers: - None "Finalizer" #3 daemon prio=8 os_prio=1 tid=0x000000001bdba800 nid=0x1f10 in Object.wait() [0x000000001d12f000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x000000076b108ee0> (a java.lang.ref.ReferenceQueue$Lock) at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:143) - locked <0x000000076b108ee0> (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) Locked ownable synchronizers: - None "Reference Handler" #2 daemon prio=10 os_prio=2 tid=0x00000000027a2800 nid=0x2214 in Object.wait() [0x000000001d02f000] java.lang.Thread.State: WAITING (on object monitor) at java.lang.Object.wait(Native Method) - waiting on <0x000000076b106b50> (a java.lang.ref.Reference$Lock) at java.lang.Object.wait(Object.java:502) at java.lang.ref.Reference.tryHandlePending(Reference.java:191) - locked <0x000000076b106b50> (a java.lang.ref.Reference$Lock) at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:153) Locked ownable synchronizers: - None "main" #1 prio=5 os_prio=0 tid=0x000000000099d800 nid=0xf2c runnable [0x000000000228e000] java.lang.Thread.State: RUNNABLE at java.io.FileInputStream.readBytes(Native Method) at java.io.FileInputStream.read(FileInputStream.java:255) at java.io.BufferedInputStream.read1(BufferedInputStream.java:284) at java.io.BufferedInputStream.read(BufferedInputStream.java:345) - locked <0x000000076b159560> (a java.io.BufferedInputStream) 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 <0x000000076b1b9ce8> (a java.io.InputStreamReader) at java.io.InputStreamReader.read(InputStreamReader.java:184) at java.io.Reader.read(Reader.java:100) at java.util.Scanner.readInput(Scanner.java:804) at java.util.Scanner.next(Scanner.java:1369) at com.myimooc.daemonthread.DaemonThreadDemo.main(DaemonThreadDemo.java:22) Locked ownable synchronizers: - None "VM Thread" os_prio=2 tid=0x000000001bd98000 nid=0x2998 runnable "GC task thread#0 (ParallelGC)" os_prio=0 tid=0x00000000026c6800 nid=0x11b0 runnable "GC task thread#1 (ParallelGC)" os_prio=0 tid=0x00000000026c8000 nid=0x26a4 runnable "GC task thread#2 (ParallelGC)" os_prio=0 tid=0x00000000026c9800 nid=0x2d6c runnable "GC task thread#3 (ParallelGC)" os_prio=0 tid=0x00000000026cb000 nid=0xab0 runnable "VM Periodic Task Thread" os_prio=2 tid=0x000000001d1f3000 nid=0x2b08 waiting on condition JNI global references: 6
總結(jié)
1.如果有daemon標(biāo)記,則當(dāng)前線程為守護(hù)線程 2.通過(guò)查看線程狀態(tài)(java.lang.Thread.State: TIMED_WAITING (sleeping)) 可以幫助我們定位到導(dǎo)致程序出現(xiàn)死鎖,或者是阻塞問(wèn)題的原因 3.tid和nid字段可以幫助我們找到CPU占有率很高的線程第四章:課程總結(jié) 4-1 課程總結(jié)
課程總結(jié)
線程創(chuàng)建的兩種方式回顧 線程創(chuàng)建的兩種方式比較 線程的聲明周期 守護(hù)線程 jsrack生成線程快照
建議
多使用Runnable這種方式創(chuàng)建線程
補(bǔ)充
1.程序中的同一資源指的是同一個(gè)Runnable對(duì)象 2.安全的賣票程序中需要加入同步(Synchronized)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/67333.html
時(shí)間:2017年07月09日星期日說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)源碼:無(wú)學(xué)習(xí)源碼:https://github.com/zccodere/s... 第一章:課程簡(jiǎn)介 1-1 課程簡(jiǎn)介 課程目標(biāo)和學(xué)習(xí)內(nèi)容 共享變量在線程間的可見(jiàn)性 synchronized實(shí)現(xiàn)可見(jiàn)性 volatile實(shí)現(xiàn)可見(jiàn)性 指令重排序 as-if-seria...
摘要:時(shí)間年月日星期六說(shuō)明本文部分內(nèi)容均來(lái)自慕課網(wǎng)。慕課網(wǎng)教學(xué)源碼學(xué)習(xí)源碼第一章課程介紹課程簡(jiǎn)介是啥讀音是輕量級(jí)的依賴注入框架說(shuō)明一個(gè)的框架需要有基礎(chǔ)什么是剝離注入輕量級(jí)代碼少易維護(hù)性能優(yōu)異,跟比較。 時(shí)間:2017年10月14日星期六說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com 教學(xué)源碼:https://github.com/zccodere/s......
時(shí)間:2017年12月01日星期五說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com 教學(xué)源碼:無(wú) 學(xué)習(xí)源碼:https://github.com/zccodere/s... 第一章:課程介紹 1-1 課程介紹 熱部署的使用場(chǎng)景 本地調(diào)式 線上發(fā)布 熱部署的使用優(yōu)點(diǎn) 無(wú)論本地還是線上,都適用 無(wú)需重啟服務(wù)器:提高開(kāi)發(fā)、調(diào)式效率、提升發(fā)布、運(yùn)維效率、降低運(yùn)維成本 前置...
時(shí)間:2017年05月24日星期三說(shuō)明:本文部分內(nèi)容均來(lái)自慕課網(wǎng)。@慕課網(wǎng):http://www.imooc.com教學(xué)示例源碼:無(wú)個(gè)人學(xué)習(xí)源碼:https://github.com/zccodere/s... 第一章:課程介紹 1-1 課程介紹 什么是定時(shí)任務(wù)調(diào)度 基于給定的時(shí)間點(diǎn),給定的時(shí)間間隔或者給定的執(zhí)行次數(shù)自動(dòng)執(zhí)行的任務(wù) 在Java中的定時(shí)調(diào)度工具 Timer:小弟,能實(shí)現(xiàn)日常60%的定...
摘要:原文鏈接編程方法論響應(yīng)式與代碼設(shè)計(jì)實(shí)戰(zhàn)序,來(lái)自于微信公眾號(hào)次靈均閣正文內(nèi)容在一月的架構(gòu)和設(shè)計(jì)趨勢(shì)報(bào)告中,響應(yīng)式編程和函數(shù)式仍舊編列在第一季度的早期采納者中。 原文鏈接:《Java編程方法論:響應(yīng)式RxJava與代碼設(shè)計(jì)實(shí)戰(zhàn)》序,來(lái)自于微信公眾號(hào):次靈均閣 正文內(nèi)容 在《2019 一月的InfoQ 架構(gòu)和設(shè)計(jì)趨勢(shì)報(bào)告》1中,響應(yīng)式編程(Reactive Programming)和函數(shù)式...
閱讀 1022·2021-11-22 14:56
閱讀 993·2021-11-11 16:54
閱讀 7793·2021-09-23 11:55
閱讀 3014·2021-09-22 15:57
閱讀 2796·2021-08-27 16:25
閱讀 674·2019-08-30 15:55
閱讀 1665·2019-08-30 15:43
閱讀 1599·2019-08-30 14:23