前言:對于java多線程的資料數不勝數,我們這里只是在學習后簡單地總結一下并給出一些小例子,本文適合java初學者。不過在開始之前,我們還是要弄明白一個問題——線程和進程有什么區別?其實一個進程是一個獨立的運行環境,它可以被看作一個程序或者一個應用,而線程是在進程中執行的一個任務,線程是進程的子集,一個進程可以有很多線程,每條線程并行執行不同的任務。不同的進程使用不同的內存空間,而所有的線程共享一片相同的內存空間。別把它和棧內存搞混,每個線程都擁有單獨的棧內存用來存儲本地數據。
1.創建線程的方法
創建線程方法一:繼承Thread類,使用子類創建
編寫繼承Thread子類MyThread
//MyThread.java
public class MyThread extends Thread{
? ?private String name;
? ?public MyThread(String name){
? ? ? this.name= name;
? ?}
? ?//繼承Thread類必須重寫run()方法
? ?@Override
? ?public void run() {
? ? ? System.out.println("name:" + name + "子線程ID:"
? ? ? + Thread.currentThread().getId());
? ?}
}
在main方法里面編寫代碼:
System.out.println("主線程ID:"+ Thread.currentThread().getId());
//創建多個子線程
for(int i = 0; i < 5; i++){
? ?String threadName = "Thread" + (i + 1);
? ?MyThread thread = new MyThread(threadName);
? ?thread.start();
}
//注:直接調用Thread的run方法,并不會在新的線程上執行,而是跟普通方法調用一樣,在當前線程上執行
MyThread threadSpec = new MyThread("ThreadSpec"); ? //特例
threadSpec.run();
說明:啟動線程是通過start()方法,而不是調用run()方法,在線程獲取cpu執行時間的時候會自動調用run()方法。
創建線程方法二:實現Runnable接口,在Runnable上定義任務,然后將Runnable交由Thread執行
編寫實現Runnable的實現類MyRunnable
//MyRunnable.java
public class MyRunnable implements Runnable {
? ?public MyRunnable(){}
? ?//實現Runnable接口必須重寫其run方法
? ?@Override
? ?public void run() {
? ? ? System.out.println("子線程ID:"+ Thread.currentThread().getId());
? ?}
}
在main方法里面編寫代碼:
MyRunnable runnable = new MyRunnable();
Thread thread = new Thread(runnable);
thread.start();
說明:和方法一對比,方法二可能有些啰嗦,但是Java只允許單繼承,如果實際情況中類需要繼承其他類,則只能選擇方法二來實現多線程。
2.使用ExecutorService、Callable、Future實現有返回結果的多線程
先編寫實現Callable的實現類MyCallable
//MyCallable.java
public class MyCallable implements Callable {
? ?private String taskIndex;
? ?MyCallable(String taskIndex){
? ? ? this.taskIndex = taskIndex;
}
? ?@Override
? ?public Object call() throws Exception {
? ? ? System.out.println(taskIndex + "號任務啟動");
? ? ? Date startDate = new Date();
? ? ? Thread.sleep(1000);
? ? ? Date endDate = new Date();
? ? ? long time = endDate.getTime() - startDate.getTime();
? ? ? System.out.println(taskIndex + "號任務終止");
? ? ? return taskIndex + "號任務返回運行結果,當前任務執行【" + time +"毫秒】";
? ?}
}
在main方法里面編寫代碼:
//使用ExecutorService、Callable、Future實現有返回結果的多線程
System.out.println("------程序開始運行-----");
Date startDate = new Date();
int taskSize = 5;
//創建一個線程池
ExecutorService pool = Executors.newFixedThreadPool(taskSize);
//創建多個有返回值的任務
List list =new ArrayList<>();
for(int i =0;i < taskSize;i++){
? ?Callable c = new MyCallable(i +"");
? ?//執行任務并獲取Future對象
? ?Future f = pool.submit(c);
? ?list.add(f);
}
//關閉線程池
pool.shutdown();
//獲取所有并發任務的運行結果
for(Future f : list){
? ?//從Future對象上獲取任務的返回值
? ?System.out.println(f.get().toString());
}
Date endDate =new Date();
System.out.println("------程序結束運行-----,程序運行了【"+ (endDate.getTime() - startDate.getTime()) +"毫秒】");
說明:ExecutorService、Callable、Future這個對象實際上都是屬于Executor框架中的功能類。想要詳細了解Executor框架的可以訪問Java程序員必備知識-多線程框架Executor詳解。實現Callable接口,執行Callable任務后,可以獲取一個Future的對象,在該對象上調用get就可以獲取到Callable任務返回的Object了。
注:以上內容是學習java 多線程后的一個簡單的總結,如果有錯誤,請各位指出,也歡迎大家前來拍磚,灰常感謝!