Docker 的優(yōu)點(diǎn)
694
2025-04-02
目錄
一、前言
二、線程和進(jìn)程
三、多線程的創(chuàng)建
多線程創(chuàng)建的兩種方式:
方式①:
方式②:
四、幾個(gè)常見的問題?
為什么要重寫run方法?
run()方法和start方法的區(qū)別?
通過繼承的方法和實(shí)現(xiàn)接口的方式創(chuàng)建多線程,哪個(gè)好?
五、線程控制
sleep:
join
setDaemon():
六、線程的生命周期
一、前言
線程可能聽起來有點(diǎn)難,其實(shí)也是非常好理解的,咱們以游戲姿勢(shì)進(jìn)入。
二、線程和進(jìn)程
進(jìn)程:是正在運(yùn)行的,進(jìn)程是資源分配的最小單位。
線程:是cpu調(diào)度的最小單位(線程依賴于進(jìn)程)。
上面可能有些難懂,打個(gè)比喻,好比你打一把王者(其實(shí)我不玩哈doge),進(jìn)程比作是你
開的那一把游戲,線程比作成每個(gè)玩家所選的英雄或者是游戲中的水晶野怪等之類的。帶著
這個(gè)比喻來理解進(jìn)程和線程的一些關(guān)系。
一個(gè)進(jìn)程有多個(gè)線程就叫多線程。是不是感覺非常好理解。
?1.線程在進(jìn)程下進(jìn)行
1.(比如你單獨(dú)的英雄角色、野怪、小兵肯定不能運(yùn)行)
?2.進(jìn)程之間不會(huì)相互影響,一個(gè)線程結(jié)束將會(huì)導(dǎo)致整個(gè)進(jìn)程結(jié)束
2.(兩把游戲之間不會(huì)有聯(lián)系和影響。你的水晶被推掉,你這把游戲就結(jié)束了)
?3.不同的進(jìn)程數(shù)據(jù)很難共享
3.(兩把游戲之間很難有聯(lián)系,有聯(lián)系的情況比如上把的敵人這把又匹配到了)
?4.同進(jìn)程下的不同線程之間數(shù)據(jù)很容易共享
4.(你開的那一把游戲,你可以看到每個(gè)玩家的狀態(tài)(生死),也可以看到每個(gè)玩家的出裝備等等)
5.進(jìn)程的使用內(nèi)存地址可以限定使用量
5.(開的房間模式,你可以設(shè)置有多少人進(jìn),當(dāng)房間滿了后,其他人就進(jìn)不去了,除非有人退出房間,其他人才能進(jìn))
三、多線程的創(chuàng)建
多線程創(chuàng)建的兩種方式:
?①:創(chuàng)建一個(gè)類繼承Thread類,并重寫run方法。
?②:創(chuàng)建一個(gè)類實(shí)現(xiàn)Runnable接口,并重寫run方法。
方式①:
MyThread類下:
public class MyThread extends Thread { @Override public void run() { for(int i=0;i<100;i++){ System.out.println(getName()+":打了"+i+"個(gè)小兵"); } } }
MyThreadText類下:
public class MyThreadText { public static void main(String[] args) { //創(chuàng)建MyThread對(duì)象 MyThread t1=new MyThread(); MyThread t2=new MyThread(); MyThread t3=new MyThread(); //設(shè)置線程的名字 t1.setName("魯班"); t2.setName("劉備"); t3.setName("亞瑟"); //啟動(dòng)線程 t1.start(); t2.start(); t3.start(); } }
效果圖:
方式②:
MyRunnable類下:
public class MyRunnable implements Runnable { @Override public void run() { for(int i=0;i<10;i++){ try {//sleep會(huì)發(fā)生異常要顯示處理 Thread.sleep(20);//暫停20毫秒 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"打了:"+i+"個(gè)小兵"); } } }
MyRunnableText類下:
public class MyRunnableText { public static void main(String[] args) { //創(chuàng)建MyRunnable類 MyRunnable mr=new MyRunnable(); //創(chuàng)建Thread類的有參構(gòu)造,并設(shè)置線程名 Thread t1=new Thread(mr,"張飛"); Thread t2=new Thread(mr,"貂蟬"); Thread t3=new Thread(mr,"呂布"); //啟動(dòng)線程 t1.start(); t2.start(); t3.start(); } }
有sleep暫停的效果圖:
四、幾個(gè)常見的問題?
為什么要重寫run方法?
因?yàn)閞un方法是用來封裝被線程執(zhí)行的代碼。
run()方法和start方法的區(qū)別?
run():封裝線程執(zhí)行的代碼,直接調(diào)用相當(dāng)于調(diào)用普通方法。就是一直到這個(gè)方法結(jié)束才出來。
start():啟動(dòng)線程,然后由JVM此線程的run()方法,可同時(shí)進(jìn)行多個(gè)對(duì)象調(diào)用start()方法。
通過繼承的方法和實(shí)現(xiàn)接口的方式創(chuàng)建多線程,哪個(gè)好?
實(shí)現(xiàn)Runable接口好,原因:
?①避免了Java單繼承的局限性
?②適合多個(gè)相同的程序代碼去處理同一資源的情況,把線程、代碼和數(shù)據(jù)有效的分離,
體現(xiàn)出來面向?qū)ο蟮脑O(shè)計(jì)思想。
五、線程控制
① sleep:
sleep的使用要進(jìn)行顯示處理異常:
public class MyRunnable implements Runnable { @Override public void run() { for(int i=0;i<20;i++){ try {//sleep會(huì)發(fā)生異常要顯示處理 Thread.sleep(20);//暫停20毫秒 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"打了:"+i+"個(gè)小兵"); } } }
啟動(dòng)線程類下:
public class MyRunnableText { public static void main(String[] args) { //創(chuàng)建MyRunnable類 MyRunnable mr=new MyRunnable(); //創(chuàng)建Thread類的有參構(gòu)造,并設(shè)置線程名 Thread t1=new Thread(mr,"劉備"); Thread t2=new Thread(mr,"貂蟬"); Thread t3=new Thread(mr,"呂布"); //啟動(dòng)線程 t1.start(); t2.start(); t3.start(); } }
這樣暫停可以每個(gè)線程一一運(yùn)行的效果:
② join:
??join是指等待這個(gè)線程執(zhí)行完才會(huì)輪到后續(xù)線程得到cpu的執(zhí)行權(quán),使用這個(gè)也要拋出異常
具體使用:
public class MyThreadText { public static void main(String[] args) throws InterruptedException {//throws拋出join出現(xiàn)的異常 //創(chuàng)建MyThread對(duì)象 MyThread t1=new MyThread(); MyThread t2=new MyThread(); MyThread t3=new MyThread(); //設(shè)置線程的名字 t1.setName("魯班"); t2.setName("劉備"); t3.setName("亞瑟"); //啟動(dòng)線程 t1.start(); t1.join();//等待t1執(zhí)行完才會(huì)輪到t2,t3搶 t2.start(); t3.start(); } }
run方法的類下:
public class MyThread extends Thread { @Override public void run() { for(int i=0;i<100;i++){ System.out.println(getName()+":打了"+i+"個(gè)小兵"); } } }
③ setDaemon():
public class MyThreadText { public static void main(String[] args) throws InterruptedException { //創(chuàng)建MyThread對(duì)象 MyThread t1=new MyThread(); MyThread t2=new MyThread(); //設(shè)置線程的名字 t1.setName("張飛"); t2.setName("關(guān)羽"); //設(shè)置守護(hù)線程 t1.setDaemon(true); t2.setDaemon(true); //設(shè)置主線程 Thread.currentThread().setName("劉備"); //啟動(dòng)線程 t1.start(); t2.start(); //設(shè)置主線程的程序 for (int i=0;i<30;i++){ System.out.println(Thread.currentThread().getName()+":"+i); } } }
run方法所在的類:
public class MyThread extends Thread { @Override public void run() { for(int i=0;i<100;i++){ System.out.println(getName()+":打了"+i+"個(gè)小兵"); } } }
為true時(shí)說明是守護(hù)線程。
?將張飛關(guān)羽設(shè)置為守護(hù)線程,劉備設(shè)置為主線程,?則當(dāng)所有的主線程結(jié)束后,守護(hù)線程也會(huì)跟著
結(jié)束,但不是立刻結(jié)束。(劉備陣亡,張飛和關(guān)羽也會(huì)跟著走,但不是立刻陣亡,畢竟"自殺"也是要時(shí)間的。)
六、線程的生命周期
Java 任務(wù)調(diào)度 多線程
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。
版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請(qǐng)聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。