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();
}
}
- 我们可以看到平时我们通过实现Runnable接口和继承Thread来重写run方法,最终归结到了run方法的调用上。一个是重写,一个是调用接口的方法。
Oracle官方文档对创建线程的说明
-
Java SE 8 API文档: docs.oracle.com/javase/8/do…
请查看java.lang.Thread的类说明文档。
-
- 将类继承Thread类重写run方法
官方原话: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 therun
method of classThread
./** * 实现线程的第一个方式 继承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(); } }
-
- 实现Runnable接口
官方原话:The other way to create a thread is to declare a class that implements the
Runnable
interface. That class then implements therun
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();
}
}
Runnable
的优点
- 业务代码与线程类创建启动等逻辑解耦。
- 依赖倒置原则:抽象不应该依赖具体,具体应该依赖抽象
Runnable
可复用,Thread则需要每次创建。- 类可以实现多个接口,而不可以继承多个对象。所以接口更好
-
如果两种方式都用会有什么效果呢?
/** * @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
类的对象,而构建一个线程的方式则有多种:比如创建线程类、实现Runnable接口、创建线程池、FutureTask等等。 -
线程池创建线程:实际是由默认的工厂代为创建Thread类来实现。
// 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创建线程,本质其实也是Thread
public interface RunnableFuture<V> extends Runnable, Future<V> {
/**
* Sets this Future to the result of its computation
* unless it has been cancelled.
*/
void run();
}
public class FutureTask<V> implements RunnableFuture<V> {
......
private volatile Thread runner;
......
-
定时器Timer:它的TimerTask其实也是实现了Runnable接口,可以看下
TimerTask
这个抽象类/** * @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); } }