作者:vbirdbest
根据原作者做了一些补充和文献带入
- 继承Thread类
- 实现Runnable接口
- 实现Callable接口
两种实现方式最终都是调用Thread类的start()方法来启动线程的。
Thread类的run()方法
@Override
public void run() {
if (target != null) { 其中的 target 为下图所指的以Runnable为类型的对象名
target.run();
}
}
Runnable、Callable接口的实现类(两者类似),都作为形参传进Thread类的有参构造函数来进行包装。再调用Thread的start方法开启线程。
到这里有一个疑问,开启线程start()方法执行的不是执行本类Thread类的run()方法内的线程吗,怎么那两种实现类重写的run()方法就被执行了?
嗯,逻辑是这样的:
1.start()方法开启线程执行了Thread类的run()方法时,发现图2中target != null。因为实现了Runnable、Callable接口的实现类被传进Thread类的有参构造函数。即target为Runnable类型的对象。
2.target不为空则执行 target.run();方法,即实现类的run()方法。
①:继承java.lang.Thread, 重写run()方法
public class Main {
public static void main(String[] args) {
new MyThread().start();
}
}
class MyThread extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId());
}
}
②:实现java.lang.Runnable接口,重写run()方法,然后使用Thread类来包装
public class Main {
public static void main(String[] args) {
// 将Runnable实现类作为Thread的构造参数传递到Thread类中,然后启动Thread类
MyRunnable runnable = new MyRunnable();
new Thread(runnable).start();
}
}
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId());
}
}
③:实现Callable接口,重写call()方法,然后包装成java.util.concurrent.FutureTask, 再然后包装成Thread
public class Main {
public static void main(String[] args) throws Exception {
// 将Callable包装成FutureTask,FutureTask也是一种Runnable
MyCallable callable = new MyCallable();
FutureTask<Integer> futureTask = new FutureTask<>(callable);
new Thread(futureTask).start();
// get方法会阻塞调用的线程
Integer sum = futureTask.get();
System.out.println(Thread.currentThread().getName() + Thread.currentThread().getId() + "=" + sum);
}
}
class MyCallable implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId() + "\t" + new Date() + " \tstarting...");
int sum = 0;
for (int i = 0; i <= 100000; i++) {
sum += i;
}
Thread.sleep(5000);
System.out.println(Thread.currentThread().getName() + "\t" + Thread.currentThread().getId() + "\t" + new Date() + " \tover...");
return sum;
}
}