執行緒(十一)兩種傳統傳統方式建立:(thread、Runnable), 執行緒池方式ExcutorServicePool
傳統方式建立執行緒:
1、繼承Thread類,重寫run方法
2、實現Runnable介面,覆蓋介面中的run方法,然後將介面實現扔給Thread
run方法探祕:
Thread原始碼中的run方法,如下:
@Override
public void run() {
if (target != null) {
target.run();
}
}
由程式碼知道,run方法中是一個if判斷,target不為空,就可以執行 target.run()
target是什麼??
private Runnable target;
由程式碼知,target就是一個Runnable介面。
最後,進入Runnable程式碼:
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
Runnable中原來還是run方法;
我自己的理解為:Thread方法實現run方法要經歷一個if語句的判斷,直接不要if判斷了,直接重寫run; 而Runnable,直接呼叫重寫run即可
總結:為什麼建立執行緒有兩種方式?
第一種:你不是要先進行if
判斷麼?我現在不判斷了,我把你的if
幹掉,我在run()
方法中自己寫程式碼,想幹啥就幹啥,即重寫Thread中的run()
方法,;
第二種:你不是要先進行if
判斷麼?行,給你一個Runnable介面讓你判斷,但你還是得呼叫我Runnable中的run()
方法啊,那我重寫我Runnable中的run()
方法不就行了!
1、Thread建立執行緒(繼承Thread)
(1)繼承Thread,呼叫run方法
(2)start()開啟執行緒
public static void main(String[] args){ Thread thread1 = new Thread(){ @Override public void run(){ try { Thread.sleep(500);//讓執行緒休息500毫秒 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName());//打印出當前執行緒名 } }; thread1.start(); }
2、Runnable建立執行緒(實現Runnable介面)
(1)實現Runnable介面,呼叫run方法
(2)start()開啟執行緒
public static void main(String[] args){
Thread thread2 = new Thread(new Runnable(){
@Override
public void run(){
try(){
Thread.sleep(1000);
} catch(Exception e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()); //讓執行緒休息500毫秒
}
});
thread2.start();
}
3、Thread和Runnable同時建立執行緒
public static void main(String[] args){
new Thread(new Runnable(){//實現runnable介面
@Override
public void run(){
try(){
Thread.sleep(1000);
} catch(Exception e){
e.printStackTrace();
}
System.out.println("Runnable:" + Thread.currentThread().getName()); //讓執行緒休息500毫秒
}
}){ //實現thread
@Override
public void run(){
try {
Thread.sleep(500);//讓執行緒休息500毫秒
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Thread:" + Thread.currentThread().getName());//打印出當前執行緒名
}
}.start();
}
經過執行發現,執行的是Thread中的run方法。
總結:
執行start()
後,肯定先在子類中找run()
方法,找到了,父類的run()
方法自然就被幹掉了,所以會打印出Thread:,如果我們現在假設子類中沒有重寫run()
方法,那麼必然要去父類找run()
方法,父類的run()
方法中就得判斷是否有Runnable傳進來,現在有一個,所以執行Runnable中的run()
方法,那麼就會列印Runnable:出來。
4、ExcutorServicePool執行緒池方法,建立執行緒
private ScheduledExecutorService pool = Executors.newScheduledThreadPool(3);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //沒有精確到毫秒
public void scheduledStatusNotify() {
ScheduledFuture<?> future = pool.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
..........
}
});
}
執行緒池的方式建立執行緒本質上還是通過第二種方法(Runnable介面),重寫run方法