三種方式
1. 繼承Thread類建立執行緒類,通過start方法開啟新執行緒
使用方式:
- 繼承Thread類,並重寫該類的run方法。
- new一個例項,通過start方法啟動新執行緒
示例
package com.thread;
public class FirstThreadTest extends Thread{
int i = 0;
//重寫run方法,run方法的方法體就是現場執行體
public void run()
{
for(;i<100;i++){
System.out.println(getName()+" "+i);
}
}
public static void main(String[] args)
{
for(int i = 0;i< 100;i++)
{
System.out.println(Thread.currentThread().getName()+" : "+i);
if(i==20)
{
new FirstThreadTest().start();
new FirstThreadTest().start();
}
}
}
}
複製程式碼
擴充套件
start和run方法的區別: start方法開啟了一個新的執行緒,使執行緒處於就緒狀態;run方法只是在當前執行緒執行例項方法,直接呼叫run方法並沒有開啟新的執行緒。
2. 實現Runnable介面
使用方式:
- 實現Runnable介面,並重寫該類的run方法。
- new一個例項,將該例項作為Thread的target建立Thread物件
- 呼叫Thread的start方法
示例
package com.thread;
public class RunnableThreadTest implements Runnable
{
private int i;
public void run()
{
for(i = 0;i <100;i++)
{
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
public static void main(String[] args)
{
for(int i = 0;i < 100;i++)
{
System.out.println(Thread.currentThread().getName()+" "+i);
if(i==20)
{
RunnableThreadTest rtt = new RunnableThreadTest();
new Thread(rtt,"新執行緒1").start();
new Thread(rtt,"新執行緒2").start();
}
}
}
}
複製程式碼
3. 實現Callable介面
使用方式
- 建立Callable介面的實現類,並實現call方法
- 建立Callable實現類的例項,並用FutureTask類來包裝該例項
- 使用FutureTask例項作為target建立Thread例項
- 呼叫Thread例項的start方法
示例
package com.thread;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;
public class CallableThreadTest implements Callable<Integer>
{
public static void main(String[] args)
{
CallableThreadTest ctt = new CallableThreadTest();
FutureTask<Integer> ft = new FutureTask<>(ctt);
for(int i = 0;i < 100;i++)
{
System.out.println(Thread.currentThread().getName()+" 的迴圈變數i的值"+i);
if(i==20)
{
new Thread(ft,"有返回值的執行緒").start();
}
}
try
{
System.out.println("子執行緒的返回值:"+ft.get());
} catch (InterruptedException e)
{
e.printStackTrace();
} catch (ExecutionException e)
{
e.printStackTrace();
}
}
@Override
public Integer call() throws Exception
{
int i = 0;
for(;i<100;i++)
{
System.out.println(Thread.currentThread().getName()+" "+i);
}
return i;
}
}
複製程式碼
對比
Runnable/Callable和Thread對比
優勢
- 通過實現介面,還可以繼承其他類
- 多個執行緒可以共享同一個target,適合資源共享
劣勢
- 程式設計稍微複雜,如果要訪問當前執行緒,則必須使用Thread.currentThread()方法
Runnable和Callable的區別
- Callable可以有返回值,Runnable沒有返回值
- Callable介面的call()方法允許丟擲異常;而Runnable介面的run()方法的異常只能在內部消化,不能繼續上拋
擴充套件:
Callable介面支援返回執行結果,此時需要呼叫FutureTask.get()方法實現,此方法會阻塞主執行緒直到獲取‘將來’結果;當不呼叫此方法時,主執行緒不會阻塞
複製程式碼