1.怎么開啟線程平绩,主要有兩種方法繼承Thread類與實現Runnable或者Callable接口,但其實Runnable與Callable很類似闸迷,只不過Callable里面定義了回調的返回值且可聲明拋出異常而已冒签。
三種創(chuàng)建線程方式對比:
在現實中一般推薦采用實現Runnable和Callable接口的方式來創(chuàng)建多線程,因為Java不支持子類多繼承笔诵,所以當線程已經繼承了Thread類就不能再繼承其他父類了返吻。
2.再看兩個創(chuàng)建線程的例子:
public class ThreadTest {
public static void main(String[] args) {
Thread thread = new Thread(){
@Override
public void run() {
while (true){
try {
sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("1: " + Thread.currentThread().getName());
System.out.println("2: " + this.currentThread().getName());
}
}
};
thread.start();
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
while (true){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("1: " + Thread.currentThread().getName());
}
}
});
thread2.start();
}
}
Thread thread = new Thread();本身就已經創(chuàng)建了線程,繼承父類run方法:
public void run() {
if (target != null) {
target.run();
}
}
可見Thread下的run方法僅僅是對線程做了個非空的判斷乎婿,但這不是我們想要的方法测僵,所以要覆蓋父類的run方法,即如上代碼所示在覆蓋的run方法中寫自己的代碼谢翎。(如果sleep(毫秒)了就要try-catch)
再回到上面兩種方法捍靠,第一個是new Thread 覆蓋run方法,第二種是new的Runnable去寫run方法森逮。
問:Runnable不是接口嗎剂公,怎么能實例化new Runnable()了?
答:因為匿名內部類吊宋,在《Java核心技術卷1》253頁的匿名內部類節(jié)中寫道:“如果構造參數的閉小括號后面跟一個開大括號纲辽,正在定義的就是匿名內部類”颜武。對于上面的new Runnable可以理解成:
class Anonymous implement Runnable(){
@ Override
public void run(){
}
}
Runnable runnable = new Anonymous();
故實質并不是實例化接口。抽象類也是一樣比如某些類abstrct Animal 本身就不應該設計成可以實例化因為“動物”是抽象的拖吼,只有具體的貓鳞上、狗才能實例化,否則沒意義吊档。
所以以下也是可以的篙议,不過要覆蓋所有接口實現的方法
問:為什么在第一種方法打印的時候可以用this第二種不可以。
答:this表示的是當前方法所指的對象怠硼,即run()所指的對象Thread鬼贱,但第二種方this指的就是new Runnable(),指不到Thread故不能用香璃。