分享Java多線程實(shí)現(xiàn)的四種方式
以下四種方式:
- 1.繼承Thread類,重寫(xiě)run方法
- 2.實(shí)現(xiàn)Runnable接口,重寫(xiě)run方法,實(shí)現(xiàn)
Runnable
接口的實(shí)現(xiàn)類的實(shí)例對(duì)象作為Thread構(gòu)造函數(shù)的target - 3.通過(guò)Callable和FutureTask創(chuàng)建線程
- 4.通過(guò)線程池創(chuàng)建線程
后面兩種可以歸結(jié)成一類:有返回值,通過(guò)Callable接口,就要實(shí)現(xiàn)call方法,這個(gè)方法的返回值是Object,所以返回的結(jié)果可以放在Object對(duì)象中。
第一種:繼承Thread類,重寫(xiě)該類的run()方法。
class MyThread extends Thread { private int i = 0; @Override public void run() { for (i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); } } } public class ThreadDemo1 { public static void main(String[] args) { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); if (i == 30) { // 創(chuàng)建一個(gè)新的線程 myThread1 此線程進(jìn)入新建狀態(tài) Thread myThread1 = new MyThread(); // 創(chuàng)建一個(gè)新的線程 myThread2 此線程進(jìn)入新建狀態(tài) Thread myThread2 = new MyThread(); // 調(diào)用start()方法使得線程進(jìn)入就緒狀態(tài) myThread1.start(); // 調(diào)用start()方法使得線程進(jìn)入就緒狀態(tài) myThread2.start(); } } } }
如上所示,繼承Thread類,通過(guò)重寫(xiě)run()方法定義了一個(gè)新的線程類MyThread
,其中run()方法的方法體代表了線程需要完成的任務(wù),稱之為線程執(zhí)行體。當(dāng)創(chuàng)建此線程類對(duì)象時(shí)一個(gè)新的線程得以創(chuàng)建,并進(jìn)入到線程新建狀態(tài)。通過(guò)調(diào)用線程對(duì)象引用的start()方法,使得該線程進(jìn)入到就緒狀態(tài),此時(shí)此線程并不一定會(huì)馬上得以執(zhí)行,這取決于CPU調(diào)度時(shí)機(jī)。
第二種:實(shí)現(xiàn)Runnable接口,并重寫(xiě)該接口的run()方法。創(chuàng)建Runnable實(shí)現(xiàn)類的實(shí)例,并以此實(shí)例作為Thread
類的target來(lái)創(chuàng)建Thread對(duì)象,該Thread對(duì)象才是真正的線程對(duì)象。
class MyRunnable implements Runnable { private int i = 0; @Override public void run() { for (i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); } } } public class ThreadDemo2 { public static void main(String[] args) { for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); if (i == 30) { // 創(chuàng)建一個(gè)Runnable實(shí)現(xiàn)類的對(duì)象 Runnable myRunnable = new MyRunnable(); // 將myRunnable作為Thread target創(chuàng)建新的線程 Thread thread1 = new Thread(myRunnable); Thread thread2 = new Thread(myRunnable); // 調(diào)用start()方法使得線程進(jìn)入就緒狀態(tài) thread1.start(); thread2.start(); } } } }
第三種:使用Callable和Future接口創(chuàng)建線程。
- 1:創(chuàng)建Callable接口的實(shí)現(xiàn)類 ,并實(shí)現(xiàn)Call方法
- 2:創(chuàng)建Callable實(shí)現(xiàn)類的實(shí)現(xiàn),使用FutureTask類包裝Callable對(duì)象,該
FutureTask
對(duì)象封裝了Callable對(duì)象的Call方法的返回值 - 3:使用FutureTask對(duì)象作為Thread對(duì)象的target創(chuàng)建并啟動(dòng)線程
- 4:調(diào)用FutureTask對(duì)象的get()來(lái)獲取子線程執(zhí)行結(jié)束的返回值\
public class ThreadDemo3 { public static void main(String[] args) { // 創(chuàng)建MyCallable對(duì)象 Callable<Integer> myCallable = new MyCallable(); //使用FutureTask來(lái)包裝MyCallable對(duì)象 FutureTask<Integer> ft = new FutureTask<Integer>(myCallable); for (int i = 0; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); if (i == 30) { //FutureTask對(duì)象作為Thread對(duì)象的target創(chuàng)建新的線程 Thread thread = new Thread(ft); //線程進(jìn)入到就緒狀態(tài) thread.start(); } } System.out.println("主線程for循環(huán)執(zhí)行完畢.."); try { //取得新創(chuàng)建的新線程中的call()方法返回的結(jié)果 int sum = ft.get(); System.out.println("sum = " + sum); } catch (InterruptedException e) { e.printStackTrace(); } catch (ExecutionException e) { e.printStackTrace(); } } } class MyCallable implements Callable<Integer> { private int i = 0; // 與run()方法不同的是,call()方法具有返回值 @Override public Integer call() { int sum = 0; for (; i < 100; i++) { System.out.println(Thread.currentThread().getName() + " " + i); sum += i; } return sum; } }
首先,我們發(fā)現(xiàn),在實(shí)現(xiàn)Callable
接口中,此時(shí)不再是run()方法了,而是call()方法,此call()
方法作為線程執(zhí)行體,同時(shí)還具有返回值!在創(chuàng)建新的線程時(shí),是通過(guò)FutureTask
來(lái)包裝MyCallable
對(duì)象,同時(shí)作為了Thread
對(duì)象的target。
第四種:通過(guò)線程池創(chuàng)建線程。
public class ThreadDemo4{ //線程池?cái)?shù)量 private static int POOL_NUM = 10; /** * @param args * @throws InterruptedException */ public static void main(String[] args) throws InterruptedException { // TODO Auto-generated method stub ExecutorService executorService = Executors.newFixedThreadPool(5); for(int i = 0; i<POOL_NUM; i++) { RunnableThread thread = new RunnableThread(); //Thread.sleep(1000); executorService.execute(thread); } //關(guān)閉線程池 executorService.shutdown(); } } class RunnableThread implements Runnable { @Override public void run() { System.out.println("通過(guò)線程池方式創(chuàng)建的線程:" + Thread.currentThread().getName() + " "); } }
ExecutorService
、Callable
都是屬于Executor
框架。返回結(jié)果的線程是在JDK1.5中引入的新特征,還有Future接口也是屬于這個(gè)框架,有了這種特征得到返回值就很方便了。
通過(guò)分析可以知道,他同樣也是實(shí)現(xiàn)了Callable
接口,實(shí)現(xiàn)了Call方法,所以有返回值。這也就是正好符合了前面所說(shuō)的兩種分類
執(zhí)行Callable任務(wù)后,可以獲取一個(gè)Future的對(duì)象,在該對(duì)象上調(diào)用get就可以獲取到Callable
任務(wù)返回的Object了。get方法是阻塞的,
即:線程無(wú)返回結(jié)果,get方法會(huì)一直等待。
到此這篇關(guān)于分享Java多線程實(shí)現(xiàn)的四種方式的文章就介紹到這了,更多相關(guān)Java多線程內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
spring使用RedisTemplate操作Redis數(shù)據(jù)庫(kù)
這篇文章主要介紹了spring使用RedisTemplate操作Redis數(shù)據(jù)庫(kù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-03-03Java編程實(shí)現(xiàn)判斷網(wǎng)上鄰居文件是否存在的方法
這篇文章主要介紹了Java編程實(shí)現(xiàn)判斷網(wǎng)上鄰居文件是否存在的方法,涉及Java針對(duì)路徑轉(zhuǎn)換及字符串操作的相關(guān)技巧,需要的朋友可以參考下2015-10-10Java中Object類常用的12個(gè)方法(小結(jié))
Java 中的 Object 方法在面試中是一個(gè)非常高頻的點(diǎn),本文主要介紹了Java中Object類常用的12個(gè)方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12Java阻塞隊(duì)列中的BlockingQueue接口詳解
這篇文章主要介紹了Java阻塞隊(duì)列中的BlockingQueue接口詳解,對(duì)于Queue而言,BlockingQueue是主要的線程安全的版本,具有阻塞功能,可以允許添加、刪除元素被阻塞,直到成功為止,BlockingQueue相對(duì)于Queue而言增加了兩個(gè)方法put、take元素,需要的朋友可以參考下2023-09-09Java利用IO流實(shí)現(xiàn)簡(jiǎn)易的記事本功能
本文將利用Java中IO流編寫(xiě)一個(gè)模擬日記本的程序,通過(guò)在控制臺(tái)輸入指令,實(shí)現(xiàn)在本地新建文件,打開(kāi)日記本和修改日記本等功能,感興趣的可以了解一下2022-05-05解決springboot配置logback-spring.xml不起作用問(wèn)題
這篇文章主要介紹了解決springboot配置logback-spring.xml不起作用問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11Java數(shù)據(jù)結(jié)構(gòu)之集合框架與常用算法詳解
Java集合框架是Java中常用的數(shù)據(jù)結(jié)構(gòu)庫(kù),包括List、Set、Map等多種數(shù)據(jù)結(jié)構(gòu),支持快速的元素添加、刪除、查找等操作,可以用于解決各種實(shí)際問(wèn)題。Java中也有多種常用算法,如排序、查找、遞歸等,在數(shù)據(jù)處理和分析中有廣泛應(yīng)用2023-04-04