一、创建线程的两种传统方式
1、在Thread子类覆盖的run方法中编写运行代码
问题:能否在run方法声明上抛出InterruptedException异常,以便省略run方法内部对Thread.sleep()语句的try…catch处理?
答:不能。
2、在传递给Thread对象的Runnable对象的run方法中编写代码
总结:查看Thread类的run()方法的源代码,可以看到其实这两种方式都是在调用Thread对象的run方法,如果Thread类的run方法没有被覆盖,并且为该Thread对象设置了一个Runnable对象,该run方法会调用Runnable对象的run方法。
3、问题:如果在Thread子类覆盖的run方法中编写了运行代码,也为Thread子类对象传递了一个Runnable对象,那么,线程运行时的执行代码是子类的run方法的代码?还是Runnable对象的run方法的代码?
答:只会运行子类的run()方法,因为根据源码是先看子类有没有run()方法, 如果有,就覆盖父类的run()方法。所以执行子类的run()方法,如果子类没有run()方法,就运行构造器里的Runnable()的run()方法。
4、问题:为什么都是采用Runnable这种方式创建线程?
答:体现了面向对象性, 因为run()方法在Runnable对象里面和Thread对象解耦。
二、代码说明
/**
* @Title: TraditionalThread.java
* @Package com.lh.threadtest
* @Description: TODO
* @author Liu
* @date 2018年1月15日 下午3:28:20
* @version V1.0
*/
package com.lh.threadtest.t1;
import java.util.concurrent.TimeUnit;
/**
* @ClassName: TraditionalThread
* @Description: 传统线程技术
* @author Liu
* @date 2018年1月15日 下午3:28:20
*
*/
public class TraditionalThread {
/***
* @Title: main
* @Description: TODO
* @param @param args
* @return void
* @throws
*/
public static void main(String[] args) {
//创建一个线程(执行线索)
Thread thread = new Thread(){
@Override
public void run() {
while(true){
System.out.println("1-" + Thread.currentThread().getName());
//不推荐
System.out.println("2-" + this.getName());
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
};
thread.start();
Thread thread2 = new Thread(new Runnable() {
public void run() {
while(true){
System.out.println("11-" + Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
thread2.start();
//new Thread(new Runnable(){..}){..run()..}.start();
/*
* Thread中run()的源码方法:
* @Override public void run() {
* if (target != null){
* target.run();
* }
* }
*
* 如果{..run()..}run方法体不为空,Thread中的run()方法将被覆盖,执行
* {..run()..}中的run方法;反之,将执行Runnable中的run方法
*/
new Thread(
new Runnable() {
public void run() {
while(true){
System.out.println("Runnable: " + Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
){
@Override
public void run() {
while(true){
System.out.println("Thread: " + Thread.currentThread().getName());
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
}
}
三、注意点
1、获取当前线程名称:Thread.currentThread().getName()。
2、静态方法不能创建内部类的实例。
3、wait()和notify()必须在synchronized代码块中写。