oracle的多线程怎么实现,创建线程的两个方法(Oracle官网说两种,所以我们就别说什么三种四种了)...
一.有多少種實現多線程的方法?
1.不同的角度有不同的答案
2.典型的答案有兩種,分別是實現Runnable接口和繼承Thread類
3.但是看原理,其實Thread類實現了Runnable接口,并且看Thread類的run方法,會發現其兩者本質是一樣的,run方法發代碼如下:
@Override
Public void run(){
if(target != null){
target.run();
}
}
方法1和方法2,也就是說“實現Runnable類”和“繼承Thread類然后重寫run()”在實現多線程本質上,并沒有區別,都最終調用了start()方法來新建線程,這兩種方法主要區別在于run()方法來源:
方法1:最終調用target.run();
方法2:run()整個都被重寫
4.還有其他的實現線程的方法,例如線程池定時器等,他們也能新建線程,但是看源碼,從沒有逃出本質,也就是實現Runnable接口和繼承Thread類。
5.所以總結來說,我們只能通過新建Thread類這一種方式來創建線程,但是類里面的run方法有兩種方式來實現,第一種是重寫run方法,第二種實現Runnable接口的run方法,然后再把該runnable實例傳遞給Thread類。除此之外,從表象上看線程池,定時器等工具類也可以創建線程,但是它們的本質都逃不過上面的范圍。
二.為什么實現Runnable接口比繼承Thread更好?
1.相比較,實現Runnable接口更好,一般都會優先考慮這種發放,除非迫不得已,我們是不考慮繼承Thread類的。原因有三點,第一點:從代碼架構考慮,具體執行的任務,即run方法,它因該和線程創建運行也就是Thread類是接偶的,不應該將兩者混為一談,所以從接偶角度來看,實現Runnable更好。第二點:如果繼承Thread類,每次新建一個任務,只能為此新建一個獨立的線程,而新建一個獨立的線程的損耗是非常大的,它需要創建然后執行,執行完后需要銷毀,而使用Runnable就可以使用線程池之類的工具,就可以大大減小創建銷毀線程帶來的損耗。第三點:繼承了Thread類后,由于java不支持雙繼承,不能再繼承其他的類,限制了代碼的課擴展性。
線程池創建線程:
public class ThreadPool{
public static void main(String[] args){
ExecutorService executorService = Executors.newCachedThreadPool();
for(int i=0; I<100;i++){
executorService.submit(new Task(){
});
}
}
}
Class Task implements Runnable{
@Override
public void run(){
try{
Thread.sleep(500);
}catch(InterruptedException e){
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName());
}
}
定時器創建線程:
public class DemoTimerTask{
public static void main(String[] args){
Timer timer = new timer();
timer.scheduleAtFixedRate(new TimerTask(){
@Override
public void run(){System.out.println(Thread.currentThread().getName());
}
},1000,1000);
}
}
匿名內部類實現線程:
public static void main(String[] args){
new Thread(){
@Override
public void run (){
System.out.println(Thread.currentThread().getName());
}
}.start();
new Thread(new Runnable(){
@Override
public void run (){
System.out.println(Thread.currentThread().getName());
}
}).start();
}
Lambda表達式實現線程:
public static void main(String[] args){
new Thread(() -> System.out.println(Thread.currentThread().getName())).start();
}
如果一個線程兩次調用start方法會怎樣?為什么?
會拋出一個異常(IllegalThreadStateException),因為在start方法第一行,就會誤檢查線程的狀態,如果不是0,即不是初始狀態,就會拋出異常,因為線程狀態是不可逆的,所以已經執行過start后,狀態改變了,就不能在執行start方法了。
start()既然也是調用的run()方法,為什么不直接調用run()而是調用start()?
因為調用start()才是真正的去啟動一個新線程,會經歷線程的各個生命周期,而如果直接調用run()方法,它就是個普通的run()方法,不會用子線程去調用,而直接用主線程執行的。
public static void main(String[] arg){
Runnable runnable = () -> {
System.out.println(Thread.currentThread().start());
};
runnable.run();
new Thread(runnable).start();
}
輸出結果:
main
Thread-0
start()執行過程:
1.檢查線程狀態。
2.加入線程組。
3.調用start0()發放啟動線程。
start()是被synchronized修飾的,可以保證線程安全。
由JVM創建的main線程和system組線程,并不會通過start()來啟動。
注意:以上就是創建線程的方法,其中代碼不保證可執行性,因為純手打,有單子字母寫錯的可能。
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的oracle的多线程怎么实现,创建线程的两个方法(Oracle官网说两种,所以我们就别说什么三种四种了)...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《艾尔登法环》DLC终于官宣!“黄金树之
- 下一篇: 当科技遇上艺术 华为影像XMAGE在巴展