這篇文章主要講解了“Java線程的基礎(chǔ)用法教程”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“Java線程的基礎(chǔ)用法教程”吧!
為昂昂溪等地區(qū)用戶(hù)提供了全套網(wǎng)頁(yè)設(shè)計(jì)制作服務(wù),及昂昂溪網(wǎng)站建設(shè)行業(yè)解決方案。主營(yíng)業(yè)務(wù)為網(wǎng)站設(shè)計(jì)制作、成都做網(wǎng)站、昂昂溪網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專(zhuān)業(yè)、用心的態(tài)度為用戶(hù)提供真誠(chéng)的服務(wù)。我們深信只要達(dá)到每一位用戶(hù)的要求,就會(huì)得到認(rèn)可,從而選擇與我們長(zhǎng)期合作。這樣,我們也可以走得更遠(yuǎn)!
進(jìn)程是操作系統(tǒng)分配資源的最小單位,而線程是程序執(zhí)行的最小單位,他們都是可以并發(fā)執(zhí)行的。一個(gè)進(jìn)程至少有一個(gè)線程,這些線程共享進(jìn)程的資源空間。
每個(gè)線程都有一個(gè)優(yōu)先級(jí),高優(yōu)先級(jí)的線程比低優(yōu)先級(jí)的線程先執(zhí)行。優(yōu)先級(jí)的取值范圍是1到10的整數(shù),默認(rèn)是5。每個(gè)線程有可能被標(biāo)記為一個(gè)守護(hù)線程。當(dāng)一個(gè)線程創(chuàng)建另外一個(gè)新的線程對(duì)象,新的線程的優(yōu)先級(jí)等于創(chuàng)建他的線程的優(yōu)先級(jí);如果新的線程對(duì)象是一個(gè)守護(hù)線程當(dāng)且僅當(dāng)創(chuàng)建他的線程是一個(gè)守護(hù)線程。
Java線程分為守護(hù)線程(Daemon Thread)和用戶(hù)線程(User Thread)。守護(hù)線程和用戶(hù)線程基本上是一樣的,唯一的區(qū)別是如果用戶(hù)線程全部退出運(yùn)行了,不管有沒(méi)有守護(hù)線程虛擬機(jī)都會(huì)退出。守護(hù)線程的作用是為其他的線程的運(yùn)行提供服務(wù),最典型的守護(hù)線程就是GC(垃圾回收期)。
創(chuàng)建一個(gè)線程類(lèi)有三種方式:
繼承Thread類(lèi)
實(shí)現(xiàn)Runnable接口
實(shí)現(xiàn)Callable接口
Thread是創(chuàng)建線程最關(guān)鍵的一個(gè)類(lèi),這個(gè)詞本身也代表線程,Thread類(lèi)實(shí)現(xiàn)了Runnable接口。
public class ThreadDemo extends Thread { public void run() { for (int i = 0; i < 60; i++) { System.out.println(getName() + ":" + i); } } } public class Demo{ public static void main(String[] args) { ThreadDemo t1 = new ThreadDemo(); ThreadDemo t2 = new ThreadDemo(); t1.start(); t2.start(); } }
Runnable是提供線程的接口,有一個(gè)抽象方法public abstract void run()
。實(shí)現(xiàn)了這個(gè)接口的類(lèi)必須實(shí)現(xiàn)它的run
方法。
public class Runnable implements Runnable{ public void run() { public void run() { for (int i = 0; i < 60; i++) { System.out.println(Thread.currentThread().getName() + ":" + i); } } } } public class Demo{ public static void main(String[] args) { RunnableDemo run = new RunnableDemo(); Thread t1 = new Thread(run); Thread t2 = new Thread(run); t1.start(); t2.start(); } }
Thread和Runnable創(chuàng)建線程不能獲取線程的返回值。從Java1.5開(kāi)始,就提供了Callable和Future,通過(guò)他們可以在任務(wù)執(zhí)行完畢之后得到任務(wù)執(zhí)行結(jié)果。
Callable接口:可以返回一個(gè)結(jié)果或者拋出一個(gè)異常的一個(gè)任務(wù),實(shí)現(xiàn)者定義一個(gè)沒(méi)有參數(shù)的call方法。區(qū)別于Thread和Runnable的run方法,Calllable任務(wù)執(zhí)行的方法是call。
Future接口:Future接口代表了異步計(jì)算的結(jié)果,提供了一些方法用于檢查計(jì)算結(jié)果是否完成,獲取計(jì)算結(jié)果等。FutureTask類(lèi)提供了Future接口的實(shí)現(xiàn),并且實(shí)現(xiàn)了Runnable接口。
public class MyCallable implements Callable<Integer> { public Integer call() { int sum = 0; for (int i = 0; i <= 100; i++) { sum += i; } return new Integer(sum); } } public class Demo{ public static void main(String[] args) { MyCallable callable = new MyCallable(); FutureTask<Integer> result = new FutureTask<Integer>(callable); new Thread(result).start(); try { Integer value = result.get(); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } }
在Thread類(lèi)中有一個(gè)內(nèi)部枚舉類(lèi)State代表了線程的狀態(tài),一個(gè)線程從創(chuàng)建到銷(xiāo)毀就是一個(gè)完整的生命周期。
public enum State { /** * 線程被創(chuàng)建,還沒(méi)有開(kāi)始運(yùn)行 */ NEW, /** * 線程運(yùn)行狀態(tài),運(yùn)行狀態(tài)的線程是正在被Java虛擬機(jī)執(zhí)行,但是也可能正在等待操作系統(tǒng)的其他資源例如處理器 */ RUNNABLE, /** * 線程阻塞狀態(tài),等待監(jiān)視器鎖。處于阻塞狀態(tài)線程是在等待監(jiān)視器鎖為了:進(jìn)入同步代碼塊/方法或者被調(diào)用后重 * 新進(jìn)入同步代碼/方法 */ BLOCKED, /** * 線程等待狀態(tài),一個(gè)線程處于等待狀態(tài)由于調(diào)用了以下這幾種方法:Object.wait;Thread.join;LockSupp * ort.park。處于等待的線程正在等待另一個(gè)線程執(zhí)行一個(gè)特定的操作。 */ WAITING, /** * 線程超時(shí)等待狀態(tài),一個(gè)線程處于超時(shí)等待狀態(tài)在一個(gè)特定的等待時(shí)間,由于調(diào)用了以下幾個(gè)方法Thread.slee * p;Object.wait(long);Thread.join(long);LockSupport.parkNanos;LockSupport.parkUntil。 */ TIMED_WAITING, /** * 線程結(jié)束狀態(tài),線程已經(jīng)執(zhí)行完成了。 */ TERMINATED; }
線程從創(chuàng)建后就在幾個(gè)狀態(tài)中切換。下面是一個(gè)線程狀態(tài)轉(zhuǎn)換圖,調(diào)用不同的方法就可以切換線程線程的狀態(tài)。
調(diào)用Object.wait();Thread.join();LockSupport.park()方法可以讓線程從運(yùn)行狀態(tài)進(jìn)入到無(wú)限等待狀態(tài)。
wait方法
是屬于Object類(lèi)的,對(duì)象調(diào)用wait方法后會(huì)讓當(dāng)前持有對(duì)象鎖的線程釋放當(dāng)前對(duì)象鎖并進(jìn)入等待隊(duì)列。對(duì)象調(diào)用notify從等待隊(duì)列隨機(jī)選擇一個(gè)線程喚醒去競(jìng)爭(zhēng)對(duì)象鎖,對(duì)象調(diào)用notifyall會(huì)喚醒等待隊(duì)列中的所有線程去競(jìng)爭(zhēng)對(duì)象鎖。
public class Demo { public static void main(String[] args) { Demo demo = new Demo(); Thread t1 = new Thread(() -> { synchronized (demo) { System.out.println("t1 start"); try { demo.wait(); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("t1 end"); } }); Thread t2 = new Thread(() -> { synchronized (demo) { System.out.println("t2 start"); System.out.println("t2 end"); demo.notify(); } }); t1.start(); t2.start(); } }
join方法
是屬于Thread類(lèi)的,join方法是阻塞調(diào)用此方法的線程,當(dāng)線程a調(diào)用線程b的b.join(long),線程a會(huì)阻塞直到線程b執(zhí)行完成。
public class Demo { public static void main(String[] args) throws Exception { System.out.println("main start"); Thread t1 = new Thread(() -> { System.out.println("t1 start"); System.out.println("t1 end"); }); t1.start(); t1.join(); System.out.println("main end"); } }
park方法
是屬于LockSupport類(lèi)的,LockSupport是一個(gè)線程阻塞工具類(lèi),所有的方法都是靜態(tài)方法,可以使用park方法來(lái)阻塞線程,使用unpart來(lái)喚醒線程。
public class Demo { public static void main(String[] args) { System.out.println("main start"); Thread t1 = new Thread(() -> { System.out.println("t1 start"); LockSupport.park(); System.out.println("t1 end"); }); t1.start(); LockSupport.unpark(t1); System.out.println("main end"); } }
調(diào)用Object.wait(long);Thread.join(long);LockSupport.park(long)方法可以讓線程從運(yùn)行狀態(tài)進(jìn)入到等待狀態(tài),直到到達(dá)等待時(shí)間或者主動(dòng)喚醒。
wait(long)方法
是屬于Object類(lèi)的,當(dāng)對(duì)象調(diào)用wait(long)后會(huì)讓當(dāng)前持有對(duì)象鎖的線程釋放掉當(dāng)前對(duì)象鎖進(jìn)入等待隊(duì)列,直到到達(dá)等待時(shí)間或者對(duì)象調(diào)用notify或者notifyall從等待隊(duì)列中喚醒線程,線程又重新開(kāi)始競(jìng)爭(zhēng)鎖。
public class Demo { public static void main(String[] args) { Demo demo = new Demo(); Thread t1 = new Thread(() -> { synchronized (demo) { for (int i = 0; i < 1000; i++) { if (i == 500) { try { demo.wait(100); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("------t1------: " + i); } } }); Thread t2 = new Thread(() -> { synchronized (demo) { for (int i = 0; i < 1000; i++) { System.out.println("------t2------: " + i); } } }); t1.start(); t2.start(); } }
join(long)方法
是屬于Thread類(lèi)的,join(long)方法是阻塞調(diào)用此方法的線程,當(dāng)線程a調(diào)用線程b的b.join(long),線程a會(huì)阻塞直到到達(dá)阻塞時(shí)間或者線程b執(zhí)行完成。
public class Demo { public static void main(String[] args) throws Exception { System.out.println("main start"); Thread t1 = new Thread(() -> { for (int i = 0; i < 1000; i++) { System.out.println("----t1----: " + i); } }); t1.start(); t1.join(1); System.out.println("main end"); } }
parkUntil(long)和parkNanos(long)
是屬于LockSupport類(lèi)的,LockSupport是一個(gè)線程阻塞工具類(lèi),所有的方法都是靜態(tài)方法,可以使用parkUntil(long)和parkNanos(long)方法來(lái)阻塞線程。parkNanons是阻塞long時(shí)間,parkUntil是阻塞截止到long時(shí)間。
public class Demo { public static void main(String[] args) { System.out.println("main start"); Thread t1 = new Thread(() -> { System.out.println("t1 start"); LockSupport.parkNanos(3000000000L); System.out.println("t1 end"); }); t1.start(); System.out.println("main end"); } }
public class Demo { public static void main(String[] args) throws Exception{ System.out.println("main start"); Thread t1 = new Thread(() -> { System.out.println("t1 start"); String dateTimeStr = "2021-04-04 14:57:00"; DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); LocalDateTime dateTime = LocalDateTime.parse(dateTimeStr, df); LockSupport.parkUntil(dateTime.toInstant(ZoneOffset.of("+8")).toEpochMilli()); System.out.println("t1 end"); }); t1.start(); System.out.println("main end"); } }
對(duì)象調(diào)用wait方法后線程會(huì)進(jìn)入無(wú)限等待狀態(tài),當(dāng)對(duì)象調(diào)用notify或者notifyAll時(shí),線程將從無(wú)限等待狀態(tài)進(jìn)入阻塞狀態(tài)。
線程處于阻塞狀態(tài),如果獲取到鎖對(duì)象,就進(jìn)入運(yùn)行狀態(tài)。
感謝各位的閱讀,以上就是“Java線程的基礎(chǔ)用法教程”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)Java線程的基礎(chǔ)用法教程這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是創(chuàng)新互聯(lián),小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!
新聞標(biāo)題:Java線程的基礎(chǔ)用法教程
URL分享:http://bm7419.com/article18/pcgedp.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供關(guān)鍵詞優(yōu)化、網(wǎng)站設(shè)計(jì)、品牌網(wǎng)站建設(shè)、全網(wǎng)營(yíng)銷(xiāo)推廣、網(wǎng)站收錄、
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶(hù)投稿、用戶(hù)轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)