我们知道传统创建线程的方式有两种:
一、继承Thread类,覆盖run()方法
// 继承Thread class MyThread extends Thread{ @Override public void run(){ // do something } } // 开启线程 MyThread t1 = new MyThread(); t1.start();
二、实现Runnable接口,覆盖run()方法,使用该Runnalbe对象构造Thread类
// 实现Runnable接口 Class MyRunnable implements Runnable{ @Override public void run(){ // do something } } // 开启线程 Thread t2 = new Thread(new MyRunnable); t2.start();
创建线程的方式很简单,不过多讨论,这里提两个问题:
问题1:能否run()方法中抛出InterruptedException异常,以便在run()方法中调用Thread.sleep()的时候,不用try...catch..
问题2:如果同时覆盖的Thread类的run()方法,也为该Thread传递了Runnable对象,那么程序运行Thread类的run()方法代码,还是执行Runnable对象的run()方法的代码呢?
解答:
问题1,明显不可以,代码写完连编译都不过,我们翻看Thread类的run()方法源码可知,
Thread类的run()方法并没有抛出异常,子类继承父类的run()方法
也就不能抛出异常,这是继承方面的知识,这里暂时不深入讨论。
源码:
class MyThread extends Thread{ @Override public void run() throws InterruptedException { Thread.sleep(1000L); } }
编译器提示:
问题2:我们知道不管使用那种方式创建线程,最终都会调用Thread类的run()方法,
翻看Thread类的源码可知,在Thread类的run方法中有以下这段代码:
if (target != null) {
target.run();
}
而这个targe就是我们在构造方法传入的Runnalbe类,到这里我们应该明白,
这里分两种情况:
1)情况1:如果覆盖了Thread类的run方法,并且没有在run方法中调用super.run()方法,
则程序只会执行Thread类中的run方法代码
2)情况2:如果覆盖了Thread类的run方法,并且在run方法中第一行中调用super.run()方法,
则程序先执行Runnable类中的run方法代码,之后再执行Thread类中的run方法代码。
源码:
package com.sam; /** * 传统线程回顾 * @author SAM * */ public class TraditionalThread { /** * @param args */ public static void main(String[] args) { new Thread(new Runnable() { // Runnable的fun方法 @Override public void run() { System.out.println("这是Runnable类的run方法 TName=" + Thread.currentThread().getName()); } }){ // Thread类的run方法 @Override public void run() { //super.run(); System.out.println("这是Thread类的run方法 TName=" + Thread.currentThread().getName()); }; }.start(); } }
程序执行结果: