创建线程到底有几种方式?
1. 权威认证
docs.oracle.com/javase/8/do… 兄弟们 官方就是权威
public class MyThread extends Thread{
public void run() {
System.out.println("[" + Thread.currentThread().getName() + "线程]: " + "MyThread类中的run方法。");
}
public static void main(String[] args) {
extendClass();
runnableMethod();
}
private static void runnableMethod() {
System.out.println("[" + Thread.currentThread().getName() + "线程]");//[main线程]
Thread myThread = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("[" + Thread.currentThread().getName() + "线程]: " + "Runnable对象的run方法");
}
});
myThread.start();//[Thread-0线程]: Runnable对象的run方法
}
private static void extendClass() {
System.out.println(Thread.currentThread().getName());//main
MyThread myThread = new MyThread();
myThread.start();//[Thread-0线程]: MyThread类中的run方法。
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
继承Thread类或者传入Runnable 注意观察方法执行的当前线程
2. 构造方法分析
public Thread() {
init(null, null, "Thread-" + nextThreadNum(), 0);
}
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
Thread(Runnable target, AccessControlContext acc) {
init(null, target, "Thread-" + nextThreadNum(), 0, acc, false);
}
public Thread(ThreadGroup group, Runnable target) {
init(group, target, "Thread-" + nextThreadNum(), 0);
}
public Thread(String name) {
init(null, null, name, 0);
}
public Thread(ThreadGroup group, String name) {
init(group, null, name, 0);
}
public Thread(Runnable target, String name) {
init(null, target, name, 0);
}
public Thread(ThreadGroup group, Runnable target, String name) {
init(group, target, name, 0);
}
public Thread(ThreadGroup group, Runnable target, String name,
long stackSize) {
init(group, target, name, stackSize);
}
兄弟们 这里有两个注意点
1.线程的命名方式 nextThreadNum() private static int threadInitNumber; private static synchronized int nextThreadNum() { return threadInitNumber++; }
2.Threa类的成员变量 private Runnable target;
3. 为什么一定要调用start方法
思考一个问题 Thread是java的类,java类到底是怎么跟操作系统线程关联上的呢?看看下面的场景
子类不重写run
public class MyThread1 extends Thread{
// public void run() {
// System.out.println("[" + Thread.currentThread().getName() + "线程]: " + "MyThread类中的run方法。");
// }
public static void main(String[] args) {
extendClass();
}
private static void extendClass() {
System.out.println(Thread.currentThread().getName());//main
MyThread1 myThread = new MyThread1();
myThread.start();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
直接调用run
public class MyThread1 extends Thread{
public void run() {
System.out.println("[" + Thread.currentThread().getName() + "线程]: " + "MyThread类中的run方法。");
}
public static void main(String[] args) {
extendClass();
}
private static void extendClass() {
System.out.println(Thread.currentThread().getName());//main
MyThread1 myThread = new MyThread1();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
myThread.run();//[main线程]: MyThread类中的run方法。
}
}
现象:没有重写run方法时什么都没发生,只有调用了start方法才会开启新的线程,当直接调用run方法时只是普通的方法调用,执行方法的是当前线程。
原因:这是Thread的run方法
public void run() {
if (target != null) {
target.run();
}
}
当MyThread没有重新run方法时,也没有传入target对象(2可知 这个是Runnable为null)所以什么都没发生。
而Thread的start()方法最终会调用native的start0,开启操作系统的线程,然后最终虚拟机回调Thread类的run方法,完成闭环。
private native void start0();
4. 总结发言
八股文的回答:
- 继承Thread类
- 实现Runnable接口
- 实现Callable和Future
- 线程池
总结发言:
Thread类是java类,代码层面继承Thread类实现Runnable接口等都是外在表现,如果要创建线程最终是需要调用Thread的start()方法执行native的start0()方法,然后虚拟机会回调Thread的run()方法。