Java線程實(shí)現(xiàn)的兩種方式解析
Java線程實(shí)現(xiàn)的兩種方式解析
1.通過繼承thread,得到一個(gè)任務(wù)類
/*注意在構(gòu)造器中啟動(dòng)這個(gè)線程的話,很容易造成this逃逸的問題,這是要注意的 * 這是通過直接集成thread來成為線程。同時(shí)在這種情況下,你可以通過調(diào)用合適的方法來 * 給thread對(duì)象賦予具體的名稱。*/ public class SimpleThread extends Thread { private int countDown=5; private static int threadCount=0; public SimpleThread() { super(Integer.toString(++threadCount));//這是給這個(gè)thread賦予名字。 start(); } public String toString(){ return "#"+getName()+"("+countDown+"), "; } public void run() { while (true) { System.out.print(this); if (--countDown == 0) { return; } } } public static void main(String[] args) { for (int i = 0; i < 5; i++) { new SimpleThread(); } } }
運(yùn)行的結(jié)果為:
#1(5),
#2(5),
#3(5),
#3(4),
#3(3),
#3(2),
#4(5),
#2(4),
#5(5),
#5(4),
#1(4),
#5(3),
#5(2),
#2(3),
#2(2),
#2(1),
#4(4),
#4(3),
#4(2),
#4(1),
#3(1),
#5(1),
#1(3),
#1(2),
#1(1),
2.通過實(shí)現(xiàn)Runnable接口,來得到一個(gè)任務(wù)類
//注意,Start()是在構(gòu)造器中調(diào)用的。這個(gè)實(shí)例相當(dāng)?shù)暮?jiǎn)單,因此可能是安全的。但是應(yīng)該注意到 //在構(gòu)造器重啟動(dòng)線程可能會(huì)變得很有問題。因?yàn)榱硗庖粋€(gè)任務(wù)可能會(huì)在構(gòu)造器結(jié)束以前就開始執(zhí)行了 //這意味著該任務(wù)能夠訪問處于不穩(wěn)定狀態(tài)的對(duì)象。這是優(yōu)選Executor而不是顯式地創(chuàng)建Thread對(duì)象的 //另外一個(gè)很重要的原因。 public class SelfManaged implements Runnable { private int countDown=5; private Thread t = new Thread(this); public SelfManaged() { t.start(); } public String toString(){ return Thread.currentThread().getName()+"("+countDown+")"; } @Override public void run() { while (true) { System.out.println(this); if (--countDown == 0) { return; } } } public static void main(String[] args) { for (int i = 0; i < 5; i++) { new SelfManaged(); } } }
最后運(yùn)行的結(jié)果為:
Thread-0(5) Thread-2(5) Thread-1(5) Thread-1(4) Thread-2(4) Thread-2(3) Thread-2(2) Thread-2(1) Thread-0(4) Thread-0(3) Thread-0(2) Thread-0(1) Thread-3(5) Thread-1(3) Thread-3(4) Thread-4(5) Thread-4(4) Thread-4(3) Thread-4(2) Thread-4(1) Thread-1(2) Thread-1(1) Thread-3(3) Thread-3(2) Thread-3(1)
3.為線程設(shè)置優(yōu)先級(jí)
但是設(shè)置優(yōu)先級(jí)只是一個(gè)建議。具體是否執(zhí)行的話,還是要看系統(tǒng)內(nèi)部的調(diào)度。
public class SimplePriorities implements Runnable { private int countDown=5; private volatile double d; private int priority; public SimplePriorities(int priority) { this.priority=priority; } public String toString(){ return Thread.currentThread()+":"+countDown; } @Override public void run() { Thread.currentThread().setPriority(priority);//為這個(gè)線程設(shè)置優(yōu)先級(jí)。 while (true) { for (int i = 0; i < 10000; i++) { d += (Math.PI + Math.E)/(double)i; if (i / 1000 == 0) { Thread.yield(); } } System.out.println(this); if (--countDown == 0) { return; } } } public static void main(String[] args) { ExecutorService exec= Executors.newCachedThreadPool(); for (int i = 0; i < 5; i++) { exec.execute(new SimplePriorities(Thread.MAX_PRIORITY)); exec.execute(new SimplePriorities(Thread.MIN_PRIORITY)); exec.shutdown(); } } }
4.繼承thread和實(shí)現(xiàn)runnable之間的區(qū)別
1、如是是實(shí)現(xiàn)了Runnable接口的話,那么就為實(shí)現(xiàn)多繼承提供了方便。因?yàn)閖ava中,只允許單繼承。
2、實(shí)現(xiàn)runnable接口可以實(shí)現(xiàn)資源的共享。
這就是它們之間的最大的區(qū)別。
下面以一個(gè)買票的例子來說明它們之間的區(qū)別。
class MyThread extends Thread{ private int ticket=10; public void run(){ for(int i=0;i<20;i++){ if(this.ticket>0){ System.out.println("賣票:ticket"+this.ticket--); } } } };
下面通過三個(gè)線程對(duì)象,同時(shí)賣票:
package org.demo.dff; public class ThreadTicket { public static void main(String[] args) { MyThread mt1=new MyThread(); MyThread mt2=new MyThread(); MyThread mt3=new MyThread(); mt1.start();//每個(gè)線程都各賣了10張,共賣了30張票 mt2.start();//但實(shí)際只有10張票,每個(gè)線程都賣自己的票 mt3.start();//沒有達(dá)到資源共享 } }
package org.demo.runnable; class MyThread implements Runnable{ private int ticket=10; public void run(){ for(int i=0;i<20;i++){ if(this.ticket>0){ System.out.println("賣票:ticket"+this.ticket--); } } } } package org.demo.runnable; public class RunnableTicket { public static void main(String[] args) { MyThread mt=new MyThread(); new Thread(mt).start();//同一個(gè)mt,但是在Thread中就不可以,如果用同一 new Thread(mt).start();//個(gè)實(shí)例化對(duì)象mt,就會(huì)出現(xiàn)異常 new Thread(mt).start(); } };
到此這篇關(guān)于Java線程實(shí)現(xiàn)的兩種方式解析的文章就介紹到這了,更多相關(guān)Java線程實(shí)現(xiàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java調(diào)用外接設(shè)備詳解(制卡機(jī))
這篇文章主要為大家詳細(xì)介紹了Java調(diào)用外接設(shè)備的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-07-07如何使用JCTools實(shí)現(xiàn)Java并發(fā)程序
這篇文章主要介紹了如何使用JCTools實(shí)現(xiàn)Java并發(fā)程序,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下2021-03-03Java如何利用return結(jié)束方法調(diào)用
這篇文章主要介紹了Java如何利用return結(jié)束方法調(diào)用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-02-02java kafka寫入數(shù)據(jù)到HDFS問題
這篇文章主要介紹了java kafka寫入數(shù)據(jù)到HDFS問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-08-08Spring @ComponentScan注解使用案例詳細(xì)講解
@ComponentScan注解的作用可以簡(jiǎn)述為:將項(xiàng)目中所有被@Component注解直接或者間接標(biāo)記的類---->組裝成BeanDefinition---->然后以key=beanName, value=BeanDefinition的形式存儲(chǔ),為后續(xù)生成bean對(duì)象做準(zhǔn)備2023-03-03使用java實(shí)現(xiàn)telnet-client工具分享
這篇文章主要介紹了使用java實(shí)現(xiàn)telnet-client工具,需要的朋友可以參考下2014-03-03JAVA實(shí)現(xiàn)漢字轉(zhuǎn)拼音功能代碼實(shí)例
這篇文章主要介紹了JAVA實(shí)現(xiàn)漢字轉(zhuǎn)拼音功能代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05JAVA如何獲取jvm和操作系統(tǒng)相關(guān)信息
這篇文章主要介紹了JAVA獲取jvm和操作系統(tǒng)相關(guān)信息,使用Java自帶的類進(jìn)行獲取系統(tǒng)運(yùn)行的相關(guān)信息,在這整理記錄分享一下,需要的朋友可以參考下2022-10-10