Java創建線程有幾種方式?
Java 創建線程有兩種方式:
1. 繼承Thread
類,並重寫run()
方法
2. 實現Runnable
接口,覆蓋接口中的run()
方法,並把Runnable
接口的實現扔給Thread
public static void main(String[] args) {
// 第一種
MyThread myThread = new MyThread();
myThread.start();
// 第二種
new Thread(() -> System.out.println("自己實現的run-2")).start();
}
public static class MyThread extends Thread {
@Override
public void run() {
System.out.println("自己實現的run-1");
}
}
Java5 之後的Executors
,Executors
工具類可以用來創建線程池。
小哥:Executors
工具類是用來創建線程池的,這個線程池可以指定線程個數,也可以不指定,也可以指定定時器的線程池,它有如下常用的方法:
newFixedThreadPool(int nThreads):創建固定數量的線程池
newCachedThreadPool():創建緩存線程池
newSingleThreadExecutor():創建單個線程
newScheduledThreadPool(int corePoolSize):創建定時器線程池
hread
裏的run()
方法具體是怎麼實現的嗎?
Thread
中的run()
方法裏東西很少,就一個 if 判斷:
@Override
public void run() {
if (target != null) {
target.run();
}
}
有個target
對象,會去判斷該變量是否爲空,非空的時候,去執行target
對象中的run()
方法,否則啥也不幹。而這個target
對象,就是我們說的Runnable
:
Runnable
類
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
這個抽象方法也是run()
!如果我們使用Runnable
接口,就需要實現這個run()
方法。由於這個Runnable
類上面標了@FunctionalInterface
註解,所以可以使用函數式編程。
假如用第一種方式:繼承了Thread
類,然後重寫了run()
方法,那麼它就不會去執行上面這個默認的run()
方法了(即不會去判斷target
),會執行我重寫的run()
方法邏輯。
假如是用的第二種方式:實現Runnable
接口的方式,那麼它會執行默認的run()
方法,然後判斷target
不爲空,再去執行我在Runnable
接口中實現的run()
方法。
那如果我既繼承了Thread
類,同時我又實現了Runnable
接口,比如這樣,最後會打印什麼信息出來呢?
public static void main(String[] args) {
new Thread(() -> System.out.println("runnable run")) {
@Override
public void run() {
System.out.println("Thread run");
}
}.start();
}
“Thread run”
其實是 new 了一個對象(子對象)繼承了Thread
對象(父對象),在子對象裏重寫了父類的run()
方法;然後父對象裏面扔了個Runnable
進去,父對象中的run()
方法就是最初那個帶有 if 判斷的run()
方法。
好了,現在執行start()
後,肯定先在子類中找run()
方法,找到了,父類的run()
方法自然就被幹掉了,所以會打印出:Thread run。
Java 語言本身的父子繼承關係,會優先執行子類重寫的方法而已