一. 類繼承Thread類創建線程
/**
*繼承Thread類創建線程的方式
*/
public class MyThreadExtendThread extends Thread{
private int i;
//重寫Thread的run方法來創建用戶線程類的執行體
@Override
public void run() {
//迭代輸出0到100的數字
for(;i<100;i++){
System.out.println(getName()+" "+i);
}
}
//main主線程
public static void main(String[] args){
for (int i=0;i<100;i++){
//非直接繼承類的線程獲得線程name需要使用Thread.currentThread().getName()
System.out.println(Thread.currentThread().getName()+" "+i);
if (i==20){
//創建第一個用戶線程,start()啓動線程
new MyThreadExtendThread().start();
//創建第二個用戶線程,start()啓動線程
new MyThreadExtendThread().start();
}
}
}
}
二. 實現runnable接口創建線程
/**
* 實現runnable接口創建線程
* Created by jeker on 17-6-25.
*/
public class MyThreadImplementRunable implements Runnable {
private int i;
//實現Runnable接口的run()方法來創建用戶線程的執行體
@Override
public void run() {
//迭代輸出0到100的數字
for (;i<100;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
//main主線程
public static void main(String[] args){
for (int i =0 ;i<100;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
if (i==20){
//創建用戶線程類實例
MyThreadImplementRunable myThreadImplementRunable = new MyThreadImplementRunable();
//以用戶線程類的實例作爲Thread的target來創建thrad對象,並制定線程名稱,即線程對象
new Thread(myThreadImplementRunable,"線程1").start();
new Thread(myThreadImplementRunable,"線程2").start();
}
}
}
}
三.使用callable和future來創建線程
import java.util.concurrent.Callable;
import java.util.concurrent.FutureTask;
/**
* 使用callable和future創建線程(使線程執行後可以有返回值)
* Created by jeker on 17-6-25.
*/
public class CallableAndFuture {
//main主線程
public static void main(String[] args) {
//創建用戶callable線程類,並實現實現callable方法
Callable<Integer> callable = new Callable<Integer>() {
//實現callable接口的call方法,來創建用戶線程的執行體,並返回相應類型的值
@Override
public Integer call() throws Exception {
int i;
for (i = 0; i < 100; i++) {
System.out.println(Thread.currentThread().getName() + " " + i);
}
return i;
}
};
//使用futureTask對象來包裝callable對象,該futureTask對象封裝了callable的返回值
FutureTask<Integer> futureTask = new FutureTask<Integer>(callable);
for (int i = 0;i<100;i++){
System.out.println(Thread.currentThread().getName()+" "+i);
if (i==20){
//使用future作爲thread的target來創建線程,實質上還是以callable來創建線程的
new Thread(futureTask,"futureTask1").start();
}
}
try {
//獲取線程的返回值通過futuretask類
System.out.println("callable的返回值爲:"+futureTask.get());
}catch(Exception ex){
ex.printStackTrace();
}
}
}
三種創建線程方式的對比:
使用方式一:
優點:簡單方便,獲取線程信息不需要使用Thread.CurrentThread.getName(),可以直接以this.getName的方式獲取.*
缺點:直接繼承了Thread類,無法再繼承其他類,擴展性差*
使用方式二:
優點:比較簡潔,可以另外繼承其他類擴展性好,同一個target創建的多個線程執行體共享一個成員變量.
缺點:獲取線程相關信息的時候需要使用Thread.CurrentThread.getName().
使用方式三:
優點:線程執行體可以有返回值,可以另外繼承其他類擴展性好,同一個target創建的多個線程執行體共享一個成員變量.
缺點:獲取線程相關信息的時候需要使用Thread.CurrentThread.getName().
綜上所述,推薦使用實現callable或runnable接口方式來創建線程.