电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

您的位置:首頁技術文章
文章詳情頁

實例代碼講解JAVA多線程

瀏覽:80日期:2022-08-31 15:25:08

進程與線程

進程是程序的一次動態執行過程,它需要經歷從代碼加載,代碼執行到執行完畢的一個完整的過程,這個過程也是進程本身從產生,發展到最終消亡的過程。多進程操作系統能同時達運行多個進程(程序),由于 CPU 具備分時機制,所以每個進程都能循環獲得自己的CPU 時間片。由于 CPU 執行速度非常快,使得所有程序好像是在同時運行一樣。

多線程是實現并發機制的一種有效手段。進程和線程一樣,都是實現并發的一個基本單位。線程是比進程更小的執行單位,線程是進程的基礎之上進行進一步的劃分。所謂多線程是指一個進程在執行過程中可以產生多個更小的程序單元,這些更小的單元稱為線程,這些線程可以同時存在,同時運行,一個進程可能包含多個同時執行的線程。進程與線程的區別如圖所示:

實例代碼講解JAVA多線程

Java中線程實現的方式

在 Java 中實現多線程有兩種手段,一種是繼承 Thread 類,另一種就是實現 Runnable 接口。下面我們就分別來介紹這兩種方式的使用。

實現 Runnable 接口

package ljz;class MyThread implements Runnable{ // 實現Runnable接口,作為線程的實現類 private String name ; // 表示線程的名稱 public MyThread(String name){ this.name = name ; // 通過構造方法配置name屬性 } public void run(){ // 覆寫run()方法,作為線程 的操作主體 for(int i=0;i<10;i++){ System.out.println(name + '運行,i = ' + i) ; } }};public class RunnableDemo01{ public static void main(String args[]){ MyThread mt1 = new MyThread('線程A ') ; // 實例化對象 MyThread mt2 = new MyThread('線程B ') ; // 實例化對象 Thread t1 = new Thread(mt1) ; // 實例化Thread類對象 Thread t2 = new Thread(mt2) ; // 實例化Thread類對象 t1.start() ; // 啟動多線程 t2.start() ; // 啟動多線程 }};

程序運行結果:

實例代碼講解JAVA多線程

繼承 Thread 類

class MyThread extends Thread{ // 繼承Thread類,作為線程的實現類 private String name ; // 表示線程的名稱 public MyThread(String name){ this.name = name ; // 通過構造方法配置name屬性 } public void run(){ // 覆寫run()方法,作為線程 的操作主體 for(int i=0;i<10;i++){ System.out.println(name + '運行,i = ' + i) ; } }};public class ThreadDemo02{ public static void main(String args[]){ MyThread mt1 = new MyThread('線程A ') ; // 實例化對象 MyThread mt2 = new MyThread('線程B ') ; // 實例化對象 mt1.start() ; // 調用線程主體 mt2.start() ; // 調用線程主體 }};

程序運行結果:

實例代碼講解JAVA多線程

從程序可以看出,現在的兩個線程對象是交錯運行的,哪個線程對象搶到了 CPU 資源,哪個線程就可以運行,所以程序每次的運行結果肯定是不一樣的,在線程啟動雖然調用的是 start() 方法,但實際上調用的卻是 run() 方法定義的主體。

Thread 類和 Runnable 接口

通過 Thread 類和 Runable 接口都可以實現多線程,那么兩者有哪些聯系和區別呢?下面我們觀察 Thread 類的定義。

public class Thread extends Object implements Runnable

從 Thread 類的定義可以清楚的發現,Thread 類也是 Runnable 接口的子類,但在Thread類中并沒有完全實現 Runnable 接口中的 run() 方法,下面是 Thread 類的部分定義。

Private Runnable target;public Thread(Runnable target,String name){ init(null,target,name,0);}private void init(ThreadGroup g,Runnable target,String name,long stackSize){ ... this.target=target;}public void run(){ if(target!=null){ target.run(); }}

從定義中可以發現,在 Thread 類中的 run() 方法調用的是 Runnable 接口中的 run() 方法,也就是說此方法是由 Runnable 子類完成的,所以如果要通過繼承 Thread 類實現多線程,則必須覆寫 run()。

實際上 Thread 類和 Runnable 接口之間在使用上也是有區別的,如果一個類繼承 Thread類,則不適合于多個線程共享資源,而實現了 Runnable 接口,就可以方便的實現資源的共享。

線程的狀態變化

要想實現多線程,必須在主線程中創建新的線程對象。任何線程一般具有5種狀態,即創建,就緒,運行,阻塞,終止。下面分別介紹一下這幾種狀態:

1 創建狀態

在程序中用構造方法創建了一個線程對象后,新的線程對象便處于新建狀態,此時它已經有了相應的內存空間和其他資源,但還處于不可運行狀態。新建一個線程對象可采用Thread 類的構造方法來實現,例如 “Thread thread=new Thread()”。

2 就緒狀態

新建線程對象后,調用該線程的 start() 方法就可以啟動線程。當線程啟動時,線程進入就緒狀態。此時,線程將進入線程隊列排隊,等待 CPU 服務,這表明它已經具備了運行條件。

3 運行狀態

當就緒狀態被調用并獲得處理器資源時,線程就進入了運行狀態。此時,自動調用該線程對象的 run() 方法。run() 方法定義該線程的操作和功能。

4 阻塞狀態

一個正在執行的線程在某些特殊情況下,如被人為掛起或需要執行耗時的輸入/輸出操作,會讓 CPU 暫時中止自己的執行,進入阻塞狀態。在可執行狀態下,如果調用sleep(),suspend(),wait() 等方法,線程都將進入阻塞狀態,發生阻塞時線程不能進入排隊隊列,只有當引起阻塞的原因被消除后,線程才可以轉入就緒狀態。

5 死亡狀態

線程調用 stop() 方法時或 run() 方法執行結束后,即處于死亡狀態。處于死亡狀態的線程不具有繼續運行的能力。

在此提出一個問題,Java 程序每次運行至少啟動幾個線程?

回答:至少啟動兩個線程,每當使用 Java 命令執行一個類時,實際上都會啟動一個 JVM,每一個JVM實際上就是在操作系統中啟動一個線程,Java 本身具備了垃圾的收集機制。所以在 Java 運行時至少會啟動兩個線程,一個是 main 線程,另外一個是垃圾收集線程。

取得和設置線程的名稱

class MyThread implements Runnable{ //實現Runnable接口 public void run(){ for(int i=0;i<3;i++){ System.Out.Println(Thread.currentThread().getName()+'運行, i='+i); //取得當前線程的名稱 } }};public class ThreadDemo{public static void main(String args[]){ MyThread my=new MyThread(); //定義Runnable子類對象 new Thread(my).start; //系統自動設置線程名稱 new Thread(my,'線程A').start(); //手工設置線程名稱 }};

程序運行結果:

實例代碼講解JAVA多線程

線程的操作方法

剛才在分析自定義模式工作原理的時候其實就已經提到了,如果想要更改Glide的默認配

線程的強制運行

在線程操作中,可以使用 join() 方法讓一個線程強制運行,線程強制運行期間,其他線程無法運行,必須等待此線程完成之后才可以繼續執行。

class MyThread implements Runnable{ // 實現Runnable接口 public void run(){ // 覆寫run()方法 for(int i=0;i<50;i++){ System.out.println(Thread.currentThread().getName() + '運行,i = ' + i) ; // 取得當前線程的名字 } }};public class ThreadJoinDemo{ public static void main(String args[]){ MyThread mt = new MyThread() ; // 實例化Runnable子類對象 Thread t = new Thread(mt,'線程'); // 實例化Thread對象 t.start() ; // 啟動線程 for(int i=0;i<50;i++){ if(i>10){try{ t.join() ; // 線程強制運行}catch(InterruptedException e){} } System.out.println('Main線程運行 --> ' + i) ; } }};

程序運行結果:

實例代碼講解JAVA多線程

線程的休眠

在程序中允許一個線程進行暫時的休眠,直接使用 Thread.sleep() 即可實現休眠。

class MyThread implements Runnable{ // 實現Runnable接口 public void run(){ // 覆寫run()方法 for(int i=0;i<50;i++){ try{Thread.sleep(500) ; // 線程休眠 }catch(InterruptedException e){ } System.out.println(Thread.currentThread().getName() + '運行,i = ' + i) ; // 取得當前線程的名字 } }};public class ThreadSleepDemo{ public static void main(String args[]){ MyThread mt = new MyThread() ; // 實例化Runnable子類對象 Thread t = new Thread(mt,'線程'); // 實例化Thread對象 t.start() ; // 啟動線程 }};

程序運行結果:

實例代碼講解JAVA多線程

中斷線程

當一個線程運行時,另外一個線程可以直接通過interrupt()方法中斷其運行狀態。

class MyThread implements Runnable{ // 實現Runnable接口 public void run(){ // 覆寫run()方法 System.out.println('1、進入run()方法') ; try{ Thread.sleep(10000) ; // 線程休眠10秒 System.out.println('2、已經完成了休眠') ; }catch(InterruptedException e){ System.out.println('3、休眠被終止') ; return ; // 返回調用處 } System.out.println('4、run()方法正常結束') ; }};public class ThreadInterruptDemo{ public static void main(String args[]){ MyThread mt = new MyThread() ; // 實例化Runnable子類對象 Thread t = new Thread(mt,'線程'); // 實例化Thread對象 t.start() ; // 啟動線程 try{ Thread.sleep(2000) ; // 線程休眠2秒 }catch(InterruptedException e){ System.out.println('3、休眠被終止') ; } t.interrupt() ; // 中斷線程執行 }};

程序運行結果:

實例代碼講解JAVA多線程

后臺線程

在 Java 程序中,只要前臺有一個線程在運行,則整個 Java 進程都不會消失,所以此時可以設置一個后臺線程,這樣即使 Java 線程結束了,此后臺線程依然會繼續執行,要想實現這樣的操作,直接使用 setDaemon() 方法即可。

class MyThread implements Runnable{ // 實現Runnable接口 public void run(){ // 覆寫run()方法 while(true){ System.out.println(Thread.currentThread().getName() + '在運行。') ; } }};public class ThreadDaemonDemo{ public static void main(String args[]){ MyThread mt = new MyThread() ; // 實例化Runnable子類對象 Thread t = new Thread(mt,'線程'); // 實例化Thread對象 t.setDaemon(true) ; // 此線程在后臺運行 t.start() ; // 啟動線程 }};

在線程類 MyThread 中,盡管 run() 方法中是死循環的方式,但是程序依然可以執行完,因為方法中死循環的線程操作已經設置成后臺運行。

線程的優先級

在 Java 的線程操作中,所有的線程在運行前都會保持在就緒狀態,那么此時,哪個線程的優先級高,哪個線程就有可能會先被執行。

class MyThread implements Runnable{ // 實現Runnable接口 public void run(){ // 覆寫run()方法 for(int i=0;i<5;i++){ try{Thread.sleep(500) ; // 線程休眠 }catch(InterruptedException e){ } System.out.println(Thread.currentThread().getName() + '運行,i = ' + i) ; // 取得當前線程的名字 } }};public class ThreadPriorityDemo{ public static void main(String args[]){ Thread t1 = new Thread(new MyThread(),'線程A') ; // 實例化線程對象 Thread t2 = new Thread(new MyThread(),'線程B') ; // 實例化線程對象 Thread t3 = new Thread(new MyThread(),'線程C') ; // 實例化線程對象 t1.setPriority(Thread.MIN_PRIORITY) ; // 優先級最低 t2.setPriority(Thread.MAX_PRIORITY) ; // 優先級最高 t3.setPriority(Thread.NORM_PRIORITY) ; // 優先級最中等 t1.start() ; // 啟動線程 t2.start() ; // 啟動線程 t3.start() ; // 啟動線程 }};

實例代碼講解JAVA多線程

從程序的運行結果中可以觀察到,線程將根據其優先級的大小來決定哪個線程會先運行,但是需要注意并非優先級越高就一定會先執行,哪個線程先執行將由 CPU 的調度決定。

線程的禮讓

在線程操作中,也可以使用 yield() 方法將一個線程的操作暫時讓給其他線程執行

class MyThread implements Runnable{ // 實現Runnable接口 public void run(){ // 覆寫run()方法 for(int i=0;i<5;i++){ try{Thread.sleep(500) ; }catch(Exception e){ } System.out.println(Thread.currentThread().getName() + '運行,i = ' + i) ; // 取得當前線程的名字 if(i==2){System.out.print('線程禮讓:') ;Thread.currentThread().yield() ; // 線程禮讓 } } }};public class ThreadYieldDemo{ public static void main(String args[]){ MyThread my = new MyThread() ; // 實例化MyThread對象 Thread t1 = new Thread(my,'線程A') ; Thread t2 = new Thread(my,'線程B') ; t1.start() ; t2.start() ; }};

程序運行結果

實例代碼講解JAVA多線程

同步以及死鎖

一個多線程的程序如果是通過 Runnable 接口實現的,則意味著類中的屬性被多個線程共享,那么這樣就會造成一種問題,如果這多個線程要操作同一個資源時就有可能出現資源同步問題。

解決方法:

同步代碼塊

synchronized(同步對象){ 需要同步的代碼 }

class MyThread implements Runnable{ private int ticket = 5 ; // 假設一共有5張票 public void run(){ for(int i=0;i<100;i++){ synchronized(this){ // 要對當前對象進行同步if(ticket>0){ // 還有票 try{ Thread.sleep(300) ; // 加入延遲 }catch(InterruptedException e){ e.printStackTrace() ; } System.out.println('賣票:ticket = ' + ticket-- );} } } }};public class SyncDemo02{ public static void main(String args[]){ MyThread mt = new MyThread() ; // 定義線程對象 Thread t1 = new Thread(mt) ; // 定義Thread對象 Thread t2 = new Thread(mt) ; // 定義Thread對象 Thread t3 = new Thread(mt) ; // 定義Thread對象 t1.start() ; t2.start() ; t3.start() ; }};

程序運行結果:

實例代碼講解JAVA多線程

同步方法

除了可以將需要的代碼設置成同步代碼塊外,也可以使用 synchronized 關鍵字將一個方法聲明為同步方法。

synchronized 方法返回值 方法名稱(參數列表){ }

class MyThread implements Runnable{ private int ticket = 5 ; // 假設一共有5張票 public void run(){ for(int i=0;i<100;i++){ this.sale() ; // 調用同步方法 } } public synchronized void sale(){ // 聲明同步方法 if(ticket>0){ // 還有票 try{Thread.sleep(300) ; // 加入延遲 }catch(InterruptedException e){e.printStackTrace() ; } System.out.println('賣票:ticket = ' + ticket-- ); } }};public class SyncDemo03{ public static void main(String args[]){ MyThread mt = new MyThread() ; // 定義線程對象 Thread t1 = new Thread(mt) ; // 定義Thread對象 Thread t2 = new Thread(mt) ; // 定義Thread對象 Thread t3 = new Thread(mt) ; // 定義Thread對象 t1.start() ; t2.start() ; t3.start() ; }};

程序運行結果

實例代碼講解JAVA多線程

從程序運行的結果可以發現,此代碼完成了與之前同步代碼同樣的功能。

死鎖

同步可以保證資源共享操作的正確性,但是過多同步也會產生問題。例如,現在張三想要李四的畫,李四想要張三的書,張三對李四說“把你的畫給我,我就給你書”,李四也對張三說“把你的書給我,我就給你畫”兩個人互相等對方先行動,就這么干等沒有結果,這實際上就是死鎖的概念。

所謂死鎖,就是兩個線程都在等待對方先完成,造成程序的停滯,一般程序的死鎖都是在程序運行時出現的。

下面以一個簡單范例說明這個概念

class Zhangsan{ // 定義張三類 public void say(){ System.out.println('張三對李四說:“你給我畫,我就把書給你。”') ; } public void get(){ System.out.println('張三得到畫了。') ; }};class Lisi{ // 定義李四類 public void say(){ System.out.println('李四對張三說:“你給我書,我就把畫給你”') ; } public void get(){ System.out.println('李四得到書了。') ; }};public class ThreadDeadLock implements Runnable{ private static Zhangsan zs = new Zhangsan() ; // 實例化static型對象 private static Lisi ls = new Lisi() ; // 實例化static型對象 private boolean flag = false ; // 聲明標志位,判斷那個先說話 public void run(){ // 覆寫run()方法 if(flag){ synchronized(zs){ // 同步張三zs.say() ;try{ Thread.sleep(500) ;}catch(InterruptedException e){ e.printStackTrace() ;}synchronized(ls){ zs.get() ;} } }else{ synchronized(ls){ls.say() ;try{ Thread.sleep(500) ;}catch(InterruptedException e){ e.printStackTrace() ;}synchronized(zs){ ls.get() ;} } } } public static void main(String args[]){ ThreadDeadLock t1 = new ThreadDeadLock() ; // 控制張三 ThreadDeadLock t2 = new ThreadDeadLock() ; // 控制李四 t1.flag = true ; t2.flag = false ; Thread thA = new Thread(t1) ; Thread thB = new Thread(t2) ; thA.start() ; thB.start() ; }};

程序運行結果

實例代碼講解JAVA多線程

以下代碼不再執行,程序進入死鎖狀態。

總結

至此關于多線程一些基本操作就介紹完了,鑒于筆者經驗有限,如果有什么不足和缺漏的地方,歡迎相互交流學習,感謝大家!

以上就是實例代碼講解JAVA多線程的詳細內容,更多關于JAVA多線程的資料請關注好吧啦網其它相關文章!

標簽: Java
相關文章:
主站蜘蛛池模板: 免费网站网址收录网_海企优网站推荐平台 | 精密机械零件加工_CNC加工_精密加工_数控车床加工_精密机械加工_机械零部件加工厂 | 隐形纱窗|防护纱窗|金刚网防盗纱窗|韦柏纱窗|上海青木装潢制品有限公司|纱窗国标起草单位 | YJLV22铝芯铠装电缆-MYPTJ矿用高压橡套电缆-天津市电缆总厂 | 南汇8424西瓜_南汇玉菇甜瓜-南汇水蜜桃价格 | 蓄电池回收,ups电池后备电源回收,铅酸蓄电池回收,机房电源回收-广州益夫铅酸电池回收公司 | 高低温试验箱-模拟高低温试验箱订制-北京普桑达仪器科技有限公司【官网】 | 流变仪-热分析联用仪-热膨胀仪厂家-耐驰科学仪器商贸 | 诗词大全-古诗名句 - 古诗词赏析 | 深圳律师咨询_深圳律师事务所_华荣【免费在线法律咨询】网 | 锂电混合机-新能源混合机-正极材料混料机-高镍,三元材料混料机-负极,包覆混合机-贝尔专业混合混料搅拌机械系统设备厂家 | 冷轧机|两肋冷轧机|扁钢冷轧机|倒立式拉丝机|钢筋拔丝机|收线机-巩义市华瑞重工机械制造有限公司 | ptc_浴霸_大巴_干衣机_呼吸机_毛巾架_电动车加热器-上海帕克 | 新材料分散-高速均质搅拌机-超声波分散混合-上海化烁智能设备有限公司 | 台湾阳明固态继电器-奥托尼克斯光电传感器-接近开关-温控器-光纤传感器-编码器一级代理商江苏用之宜电气 | 成都办公室装修-办公室设计-写字楼装修设计-厂房装修-四川和信建筑装饰工程有限公司 | 交变/复合盐雾试验箱-高低温冲击试验箱_安奈设备产品供应杭州/江苏南京/安徽马鞍山合肥等全国各地 | 一航网络-软件测评官网| 德国进口电锅炉_商用电热水器_壁挂炉_电采暖器_电热锅炉[德国宝] | 冷镦机-多工位冷镦机-高速冷镦机厂家-温州金诺机械设备制造有限公司 | 压力控制器,差压控制器,温度控制器,防爆压力控制器,防爆温度控制器,防爆差压控制器-常州天利智能控制股份有限公司 | 留学生辅导网-在线课程论文辅导-留学生挂科申诉机构 | 烘干设备-热泵烘干机_广东雄贵能源设备有限公司 | 冰雕-冰雪世界-大型冰雕展制作公司-赛北冰雕官网 | 温控器生产厂家-提供温度开关/热保护器定制与批发-惠州市华恺威电子科技有限公司 | Eiafans.com_环评爱好者 环评网|环评论坛|环评报告公示网|竣工环保验收公示网|环保验收报告公示网|环保自主验收公示|环评公示网|环保公示网|注册环评工程师|环境影响评价|环评师|规划环评|环评报告|环评考试网|环评论坛 - Powered by Discuz! | 探鸣起名网-品牌起名-英文商标起名-公司命名-企业取名包满意 | 菲希尔X射线测厚仪-菲希尔库伦法测厚仪-无锡骏展仪器有限责任公司 | 工业用品一站式采购平台|南创工品汇-官网|广州南创 | LED太阳能中国结|发光红灯笼|灯杆造型灯|节日灯|太阳能灯笼|LED路灯杆装饰造型灯-北京中海轩光电 | 贝壳粉涂料-内墙腻子-外墙腻子-山东巨野七彩贝壳漆业中心 | 东莞注册公司-代办营业执照-东莞公司注册代理记账-极刻财税 | 压缩空气检测_气体_水质找上海京工-服务专业、价格合理 | 液晶拼接屏厂家_拼接屏品牌_拼接屏价格_监控大屏—北京维康 | 车充外壳,车载充电器外壳,车载点烟器外壳,点烟器连接头,旅行充充电器外壳,手机充电器外壳,深圳市华科达塑胶五金有限公司 | 污水/卧式/潜水/钻井/矿用/大型/小型/泥浆泵,价格,参数,型号,厂家 - 安平县鼎千泵业制造厂 | 电磁流量计厂家_涡街流量计厂家_热式气体流量计-青天伟业仪器仪表有限公司 | CNC机加工-数控加工-精密零件加工-ISO认证厂家-鑫创盟 | PCB接线端子_栅板式端子_线路板连接器_端子排生产厂家-置恒电气 喷码机,激光喷码打码机,鸡蛋打码机,手持打码机,自动喷码机,一物一码防伪溯源-恒欣瑞达有限公司 假肢-假肢价格-假肢厂家-河南假肢-郑州市力康假肢矫形器有限公司 | 长沙一级消防工程公司_智能化弱电_机电安装_亮化工程专业施工承包_湖南公共安全工程有限公司 | 广州中央空调回收,二手中央空调回收,旧空调回收,制冷设备回收,冷气机组回收公司-广州益夫制冷设备回收公司 |