Java 多線程實(shí)現(xiàn)的三種方式
Java 多線程實(shí)現(xiàn)方式主要有三種:繼承 Thread 類、實(shí)現(xiàn) Runnable 接口、使用 ExecutorService、Callable、Future 實(shí)現(xiàn)有返回結(jié)果的多線程。其中前兩種方式線程執(zhí)行完后都沒(méi)有返回值,只有最后一種是帶返回值的。
1、繼承 Thread 類實(shí)現(xiàn)多線程
繼承 Thread 類的方法盡管被我列為一種多線程實(shí)現(xiàn)方式,但 Thread 本質(zhì)上也是實(shí)現(xiàn)了 Runnable 接口的一個(gè)實(shí)例,它代表一個(gè)線程的實(shí)例,并且,啟動(dòng)線程的唯一方法就是通過(guò) Thread 類的 start () 實(shí)例方法。start () 方法是一個(gè) native 方法,它將啟動(dòng)一個(gè)新線程,并執(zhí)行 run () 方法。這種方式實(shí)現(xiàn)多線程很簡(jiǎn)單,通過(guò)自己的類直接 extend Thread,并復(fù)寫(xiě) run () 方法,就可以啟動(dòng)新線程并執(zhí)行自己定義的 run () 方法。例如:
1 public class MyThread extends Thread {
2 public void run() {
3 System.out.println("MyThread.run()");
4 }
5 }
在合適的地方啟動(dòng)線程如下:
MyThread myThread1 = new MyThread();
MyThread myThread2 = new MyThread();
myThread1.start();
myThread2.start();
2、實(shí)現(xiàn) Runnable 接口方式實(shí)現(xiàn)多線程
如果自己的類已經(jīng) extends 另一個(gè)類,就無(wú)法直接 extends Thread,此時(shí),必須實(shí)現(xiàn)一個(gè) Runnable 接口,如下:
public class MyThread extends OtherClass implements Runnable {
public void run() {
System.out.println("MyThread.run()");
}
}
為了啟動(dòng) MyThread,需要首先實(shí)例化一個(gè) Thread,并傳入自己的 MyThread 實(shí)例:
MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();
事實(shí)上,當(dāng)傳入一個(gè) Runnable target 參數(shù)給 Thread 后,Thread 的 run () 方法就會(huì)調(diào)用 target.run (),參考 JDK 源代碼:
public void run() {
if (target != null) {
target.run();
}
}
3、使用 ExecutorService、Callable、Future 實(shí)現(xiàn)有返回結(jié)果的多線程
ExecutorService、Callable、Future 這個(gè)對(duì)象實(shí)際上都是屬于 Executor 框架中的功能類。想要詳細(xì)了解 Executor 框架的可以訪問(wèn) http://www.javaeye.com/topic/366591 ,這里面對(duì)該框架做了很詳細(xì)的解釋。返回結(jié)果的線程是在 JDK1.5 中引入的新特征,確實(shí)很實(shí)用,有了這種特征我就不需要再為了得到返回值而大費(fèi)周折了,而且即便實(shí)現(xiàn)了也可能漏洞百出。
可返回值的任務(wù)必須實(shí)現(xiàn) Callable 接口,類似的,無(wú)返回值的任務(wù)必須 Runnable 接口。執(zhí)行 Callable 任務(wù)后,可以獲取一個(gè) Future 的對(duì)象,在該對(duì)象上調(diào)用 get 就可以獲取到 Callable 任務(wù)返回的 Object 了,再結(jié)合線程池接口 ExecutorService 就可以實(shí)現(xiàn)傳說(shuō)中有返回結(jié)果的多線程了。下面提供了一個(gè)完整的有返回結(jié)果的多線程測(cè)試?yán)?,?JDK1.5 下驗(yàn)證過(guò)沒(méi)問(wèn)題可以直接使用。代碼如下:
import java.util.concurrent.*;
import java.util.Date;
import java.util.List;
import java.util.ArrayList;
/**
* 有返回值的線程
*/
@SuppressWarnings("unchecked")
public class Test {
public static void main(String[] args) throws ExecutionException,
InterruptedException {
System.out.println("----程序開(kāi)始運(yùn)行----");
Date date1 = new Date();
int taskSize = 5;
// 創(chuàng)建一個(gè)線程池
ExecutorService pool = Executors.newFixedThreadPool(taskSize);
// 創(chuàng)建多個(gè)有返回值的任務(wù)
List<Future> list = new ArrayList<Future>();
for (int i = 0; i < taskSize; i++) {
Callable c = new MyCallable(i + " ");
// 執(zhí)行任務(wù)并獲取Future對(duì)象
Future f = pool.submit(c);
// System.out.println(">>>" + f.get().toString());
list.add(f);
}
// 關(guān)閉線程池
pool.shutdown();
// 獲取所有并發(fā)任務(wù)的運(yùn)行結(jié)果
for (Future f : list) {
// 從Future對(duì)象上獲取任務(wù)的返回值,并輸出到控制臺(tái)
System.out.println(">>>" + f.get().toString());
}
Date date2 = new Date();
System.out.println("----程序結(jié)束運(yùn)行----,程序運(yùn)行時(shí)間【"
+ (date2.getTime() - date1.getTime()) + "毫秒】");
}
}
class MyCallable implements Callable<Object> {
private String taskNum;
MyCallable(String taskNum) {
this.taskNum = taskNum;
}
public Object call() throws Exception {
System.out.println(">>>" + taskNum + "任務(wù)啟動(dòng)");
Date dateTmp1 = new Date();
Thread.sleep(1000);
Date dateTmp2 = new Date();
long time = dateTmp2.getTime() - dateTmp1.getTime();
System.out.println(">>>" + taskNum + "任務(wù)終止");
return taskNum + "任務(wù)返回運(yùn)行結(jié)果,當(dāng)前任務(wù)時(shí)間【" + time + "毫秒】";
}
}
代碼說(shuō)明:
上述代碼中 Executors 類,提供了一系列工廠方法用于創(chuàng)先線程池,返回的線程池都實(shí)現(xiàn)了 ExecutorService 接口。
public static ExecutorService newFixedThreadPool (int nThreads) 創(chuàng)建固定數(shù)目線程的線程池。
public static ExecutorService newCachedThreadPool () 創(chuàng)建一個(gè)可緩存的線程池,調(diào)用 execute 將重用以前構(gòu)造的線程(如果線程可用)。如果現(xiàn)有線程沒(méi)有可用的,則創(chuàng)建一個(gè)新線程并添加到池中。終止并從緩存中移除那些已有 60 秒鐘未被使用的線程。
public static ExecutorService newSingleThreadExecutor () 創(chuàng)建一個(gè)單線程化的 Executor。
public static ScheduledExecutorService newScheduledThreadPool (int corePoolSize) 創(chuàng)建一個(gè)支持定時(shí)及周期性的任務(wù)執(zhí)行的線程池,多數(shù)情況下可用來(lái)替代 Timer 類。
ExecutoreService 提供了 submit () 方法,傳遞一個(gè) Callable,或 Runnable,返回 Future。如果 Executor 后臺(tái)線程池還沒(méi)有完成 Callable 的計(jì)算,這調(diào)用返回 Future 對(duì)象的 get () 方法,會(huì)阻塞直到計(jì)算完成。
IDEA 保姆級(jí)安裝教程:??http://note.youdao.com/s/Wq2GSETJ??。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-426497.html
計(jì)算機(jī)專業(yè)常用畢業(yè)設(shè)計(jì)集合:??http://note.youdao.com/s/PIJHOqnk??。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-426497.html
到了這里,關(guān)于Java 多線程實(shí)現(xiàn)的三種方式的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!