Java SE 8 API文檔: docs.oracle.com/javase/8/do…java
請查看java.lang.Thread的類說明文檔。api
官方原話:There are two ways to create a new thread of execution. One is to declare a class to be a subclass of Thread
. This subclass should override the run
method of class Thread
.oracle
/** * 實現線程的第一個方式 繼承Thread * @author yiren */
public class MyThread extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " Thread running...");
}
public static void main(String[] args) throws IOException {
new MyThread().start();
System.in.read();
}
}
複製代碼
官方原話:The other way to create a thread is to declare a class that implements the Runnable
interface. That class then implements the run
method.異步
/** * 實現線程的第二個方式 實現Runnable接口 * @author yiren */
public class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " Runnable running...");
}
public static void main(String[] args) throws IOException {
new Thread(new MyRunnable()).start();
System.in.read();
}
}
複製代碼
Thread
,每次想建一個異步任務,咱們都須要去創建一個獨立的線程。而建立一個線程的消耗是比較大的,若是是使用Runnable
,咱們就能夠很好得利用線程池之類的工具,這樣能夠大大減小建立和銷燬線程的損耗。節省資源。Thread
的類事後,該類就沒法再繼承其餘類,大大限制了可擴展性。/* What will be run. */
private Runnable target;
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
private void init(ThreadGroup g, Runnable target, String name, long stackSize) {
init(g, target, name, stackSize, null, true);
}
private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc, boolean inheritThreadLocals) {
......
this.target = target;
......
}
@Override
public void run() {
if (target != null) {
target.run();
}
}
複製代碼
兩種方法的本質(由上面的Thread類的源代碼可知)ide
Thread
是整個run()
方法被重寫Runnable
最終是Runnable
的run
方法被target.run()
調用若是兩種方式都用會有什麼效果呢?微服務
/** * @author yiren */
public class MyThreadAndRunnable {
public static void main(String[] args) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " runnable running...");
}
}
) {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " thread running...");
}
};
// 這個地方應該是執行重寫Thread類的run方法中的邏輯!
thread.start();
}
}
複製代碼
Thread
的run()
方法就是調用target.run()
,若是重寫那也就沒有調用target.run()
了。準確來講,建立線程只有一種方式,那就是構建Thread
類,而實現線程的執行單元有兩種方法,就是上面說的兩種。工具
線程池建立線程學習
/** * wrong 線程池建立 * * @author yiren */
public class ThreadPoolExample {
public static void main(String[] args) {
ExecutorService executorService = Executors.newCachedThreadPool();
for (int i = 0; i < 1000; i++) {
executorService.submit(() -> {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
});
}
}
}
// Executors中的DefaultThreadFactory
static class DefaultThreadFactory implements ThreadFactory {
private static final AtomicInteger poolNumber = new AtomicInteger(1);
private final ThreadGroup group;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private final String namePrefix;
DefaultThreadFactory() {
SecurityManager s = System.getSecurityManager();
group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
namePrefix = "pool-" +
poolNumber.getAndIncrement() +
"-thread-";
}
public Thread newThread(Runnable r) {
Thread t = new Thread(group, r,
namePrefix + threadNumber.getAndIncrement(),
0);
if (t.isDaemon())
t.setDaemon(false);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
return t;
}
}
複製代碼
newThread()
方法可知,即便是線程池,本質上仍是使用Thread
的建立線程。Callable和FutureTask建立線程大數據
由上UML圖可知,實際上內部仍是使用的Thread和Runnable來實現的。this
定時器Timer
/** * @author yiren */
public class TimerExample {
public static void main(String[] args) {
Timer timer = new Timer();
// 每隔1s打印下本身的名字
timer.scheduleAtFixedRate(new TimerTask() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + " timer running...");
}
}, 1000, 1000);
}
}
複製代碼
TimerTask
這個抽象類匿名內部類、Lambda表達式 (本質也是同樣的)
/** * 匿名內部類 * @author yiren */
public class AnonymousInnerClassExample {
public static void main(String[] args) {
new Thread() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}.start();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}).start();
}
}
/** * lambda表達式 * @author yiren */
public class LambdaExample {
public static void main(String[] args) {
new Thread(() -> System.out.println(Thread.currentThread().getName())).start();
}
}
複製代碼