首先,在java中主要由两种方式创建线程
方式1:继承Thread,然后重写run方法,最后调用start启动线程
Thread thread1 = new Thread() {
@Override
public void run() {
while(true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("currentThread thread: " + Thread.currentThread().getName());
}
}
};
thread1.start();
方式2:继承Runnable接口,然后传给Thread对象,最后调用starg启动线程
Thread thread2 = new Thread(new Runnable() {
public void run() {
while(true) {
System.out.println("1");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("currentThread thread: " + Thread.currentThread().getName());
}
}
}
).start();
public void run() {
if (target != null) {
target.run();
}
}
而这个target是Thread类中的一个Runnable对象
/* What will be run. */
private Runnable target;
然后再构造时如果有传入Runnable对象则会调用init方法对target进行赋值
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
所以当有传入Runnable方法时的Thread,在调用start时会调用Runnable中的run方法。
但大部分的写法都是采用第二种写法,因为第二种写法的思路很清晰:构造一个线程,然后这个传入一个线程的执行方法,而这个方法便是Runnable的run方法,就像pthread中的回调函数一样,更符合面向对象的过程。
当然根据多态,如果既传入了Runnable又重写了run方法的Thread的子类,是肯定会调用子类重写的run方法。
Thread thread2 = new Thread(new Runnable() {
public void run() {
while(true) {
System.out.println("1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("currentThread thread: " + Thread.currentThread().getName());
}
}
}
){
@Override
public void run() {
System.out.println("2");
while(true) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("currentThread thread: " + Thread.currentThread().getName());
System.out.println("this thread: " + this.getName());
}
}
};
thread2.start();
控制台肯定只会先打印2
2
currentThread thread: Thread-1
this thread: Thread-1