先看一下API文档:
调用start()方法的时候为什么会产生两个线程呢?
API说结果会有两个线程同时并发运行,其实这样:在运行run的过程中产生了一个线程,启动start()的方法又是一个线程,例如以下代码的这个线程是main线程
public static void main(String[] args) { Thread t = new Thread("READ-Thread"){ @Override public void run() { // 获取“当前线程”的名字 println(Thread.currentThread().getName()); // READ-Thread线程 readFromDataBase(); } }; t.start(); // main线程 } private static void println(String message) { System.out.println(message); }
一个线程不能调用start()方法多次,否则就会报错
public static void main(String[] args) { Thread t = new Thread("READ-Thread"){ @Override public void run() { System.out.println("我是READ-Thread线程"); } }; t.start(); t.start(); }
我们为什么重写了他的run()方法要去调用start()方法去执行呢?如果调用run()方法可以吗?
public static void main(String[] args) {
Thread t = new Thread("READ-Thread"){
@Override
public void run() {
println(Thread.currentThread().getName()); // main
readFromDataBase();
}
};
t.run();
}
private static void println(String message) {
System.out.println(message);
}
- 结果输出的线程为main,并没有去启动线程"READ-Thread",也就是说再线程生命周期当中New了但没有调用start()方法就不会存在另外一个线程。
这么做的好处是什么?
首先 Thread 是实现了 Runnable 接口的 现在我们先不管它,先来看一下start()方法的源代码:
那他是做什么的呢?
- 对于开发者来说,可能写程序的过程中会遇到一些问题:
- 程序的算法可能已经定了,其中有一些逻辑可能是多变的,那我就想把它抽象出来,让子类去实现。
- 比如输出一个message在中间了能要加"*"号,或者其他的符号,那先把他定下来,针对不同的情况作出不同的实现方式
- 对于开发者来说,可能写程序的过程中会遇到一些问题:
public final void print(String message) {
System.out.println("################");
wrapPrint(message);
System.out.println("################");
}
protected void wrapPrint(String message) {
}
public static void main(String[] args) {
TemplateMethod t1 = new TemplateMethod(){
@Override
protected void wrapPrint(String message) {
System.out.println("*"+message+"*");
}
};
t1.print("Hello Thread");
TemplateMethod t2 = new TemplateMethod(){
@Override
protected void wrapPrint(String message) {
System.out.println("+"+message+"+");
}
};
t2.print("Hello Thread");
}
/*
注意:
wrapPrint可以写成一个空的实现,也可以写成抽象方法,
start方法里面没有写成抽象的,那我也不写成抽象的,
在真正的模板方法里面要写成抽象类,抽象方法,这里不需要。
*/
这就是start()方法的巧妙之处,也就是说start()方法不知道你的业务逻辑到底是什么,主要提供了一个启动线程的方法,那它就抽象出一个Runnable接口(Thread默认实现了),接口里面有个run()方法, run()方法实不实现都可以,实现了之后就写自己的逻辑代码,就像上面的例子一样。
疑惑:重写的是run()方法为何要调用start()方法呢?
- 答案:其实他是巧妙的用了模板方法的技巧