新手學(xué)習(xí)安卓后热鞍,發(fā)現(xiàn)還是需要補(bǔ)習(xí)JAVA相關(guān)內(nèi)容引瀑,尤其是多線程編程趣斤,以下資料整理自《瘋狂Java講義(第三版)》
1線程的創(chuàng)建和啟動(dòng)(三種方式)
1.1 繼承Thread類創(chuàng)建線程類
public class MyThread1 extends Thread{
//整形變量i 為繼承Thread的MyThread類的實(shí)例變量讨衣,因?yàn)槌绦蛎看蝿?chuàng)建線程對(duì)象時(shí)
//都會(huì)創(chuàng)建一個(gè)MyThread對(duì)象方援,所以多個(gè)MyThread對(duì)象不共享該實(shí)例變量
private int i;
//重寫run() 方法没炒,該方法為線程執(zhí)行體
public void run(){
//此處為線程執(zhí)行體代碼
Do Something;
//通過繼承Thread類獲取當(dāng)前線程對(duì)象可以直接使用this
System.out.println(this.getName());
}
public static void main(String[] args){
System.out.println(Thread.currentTread().getName());
//線程啟動(dòng)使用start()方法,而非run()方法
new MyThread1.start();
}
}
1.2 實(shí)現(xiàn)Runnable接口創(chuàng)建線程類
/**
*
**/
public class MyThread2 implements Runnable{
//Runnable實(shí)現(xiàn)類的對(duì)象只是線程的target,多個(gè)線程共享一個(gè)target送火,
//所以多個(gè)線程可以共享同一個(gè)線程類的實(shí)例變量
private int i;
public void run(){
Do Something;
//通過Runnable接口獲取當(dāng)前線程對(duì)象只能使用Thread.currentTread()方法
System.out.println(Thread.currentTread().getName());
}
public static void main(String[] args){
//創(chuàng)建Runnable的實(shí)現(xiàn)類的對(duì)象
MyThread2 myThread2 = new MyThread2();
//以Runnable實(shí)現(xiàn)類的對(duì)象作為Thread的target來創(chuàng)建Thread線程對(duì)象
new Thread(myThread2).start();
//也可以在創(chuàng)建Thread對(duì)象時(shí)指定線程的名稱
new Thread(myThread2,"指定名稱的線程").start();
}
}
1.3 使用Callable和Future創(chuàng)建線程
Future 接口中定義的公共方法
- boolean cancel(boolean mayInterruptIfRunning):試圖取消Future里關(guān)聯(lián)的callable任務(wù)
- V get():返回callable任務(wù)中call()的返回值拳话。該方法線程阻塞
- V get(long timeout,TimeUnit unit):返回callable任務(wù)中call()的返回值,該方法最多阻塞timeout和unit指定的時(shí)間种吸,
若指定時(shí)間內(nèi)沒有返回值弃衍,則會(huì)拋出TimeoutException - boolean isCancelled():如果在Callable任務(wù)正常完成前取消則返回true。
- boolean isDone():如果Callable任務(wù)已經(jīng)完成坚俗,則返回true镜盯。
創(chuàng)建線程步驟如下
- 創(chuàng)建Callabled接口實(shí)現(xiàn)類,實(shí)現(xiàn)call()方法猖败,該call()方法將作為線程執(zhí)行體速缆,且該call()方法有返回值,再創(chuàng)建Callable實(shí)現(xiàn)類的實(shí)例恩闻。
- 使用FutureTask類來包裝Callable對(duì)象艺糜,該FutureTask對(duì)象封裝了該Callable對(duì)象的call()方法的返回值。
- 使用FutureTask對(duì)象作為Thread對(duì)象的target創(chuàng)建并啟動(dòng)新的線程幢尚。
- 調(diào)用FutureTask對(duì)象的get()方法獲得子線程執(zhí)行結(jié)束后的返回值破停。
/**
*
**/
public class MyThread3{
public static void main(String[] args){
//使用匿名內(nèi)部類創(chuàng)建callable<Integer>對(duì)象,也可以使用Lambda表達(dá)式
//使用FutureTask來包裝Callable對(duì)象
FutureTask<Integer> task = new FutureTask<Integer>(new Callable<Integer>(){
@Override
public Integer call() throws Exception {
int i = 100;
return i;
}
});
new Thread(task,"有返回值的線程").start();
try{
//get()方法獲得子線程執(zhí)行結(jié)束后的返回值
System.out.println("子線程的返回值" + task.get());
}
catch(Exception e){
e.printStackTrace();
}
}
}
1.4 三種方式對(duì)比
采用實(shí)現(xiàn)Runnable尉剩、Callable接口的方式創(chuàng)建多線程的優(yōu)缺點(diǎn)
- 線程類只實(shí)現(xiàn)了Runnable或者Callable接口真慢,可以繼承其他類。
- 這種方式下多個(gè)線程可以共享一個(gè)target對(duì)象边涕,所以非常適合多個(gè)相同線程來處理同一份資源的情況晤碘。
- 如需訪問當(dāng)前線程,需要使用Thread.currentThread()方法功蜓。
- 總體還是建議使用這兩種方法來創(chuàng)建多線程
采用繼承Thread類的方式創(chuàng)建多線程的優(yōu)缺點(diǎn)
- 因?yàn)橐呀?jīng)繼承了Thread類园爷,所以不能繼承其他類。
- 如需訪問當(dāng)前線程式撼,直接使用this來獲取當(dāng)前線程童社。