Java?Runnable和Thread實現(xiàn)多線程哪個更好你知道嗎
實現(xiàn)Runnable 接口比繼承Thread 類的方式更好:
(1)可以避免由于Java單繼承帶來的局限性;
(2)可以實現(xiàn)業(yè)務(wù)執(zhí)行邏輯和數(shù)據(jù)資源的分離;
(3)可以與線程池配合使用,從而管理線程的生命周期;
1. 避免由于Java單繼承帶來的局限性
如果異步邏輯所在類已經(jīng)繼承了一個基類,就沒有辦法再繼承Thread類。比如,當一個Dog類繼承了Pet類,再要繼承Thread類就不行了。所以在已經(jīng)存在繼承關(guān)系的情況下,只能使用實現(xiàn)Runnable接口的方式。
public class ThreadTask extends Thread {
// 線程的執(zhí)行體
@Override
public void run() {
System.out.println("線程執(zhí)行的任務(wù)");
}
}
public class RunnableTask implements Runnable {
// 線程的執(zhí)行體
@Override
public void run() {
System.out.println("線程執(zhí)行的任務(wù)");
}
}
2. 可以實現(xiàn)業(yè)務(wù)執(zhí)行邏輯和數(shù)據(jù)資源的分離
邏輯和數(shù)據(jù)更好分離。通過實現(xiàn)Runnable接口的方法創(chuàng)建多線程更加適合同一個資源被多段業(yè)務(wù)邏輯并行處理的場景。在同一個資源被多個線程邏輯異步、并行處理的場景中,通過實現(xiàn)Runnable接口的方式設(shè)計多個target執(zhí)行目標類可以更加方便、清晰地將執(zhí)行邏輯和數(shù)據(jù)存儲分離,更好地體現(xiàn)了面向?qū)ο蟮脑O(shè)計思想。
注意:并不是繼承Thread類不能實現(xiàn)資源共享,而是沒有實現(xiàn)Runnable接口更方便,更清晰,他們兩的主要區(qū)別就是類和接口的區(qū)別,但是我們一般多用Runnable。
(1) 通過繼承Thread類的方式實現(xiàn)多線程,數(shù)據(jù)資源和業(yè)務(wù)執(zhí)行邏輯是耦合在一起的, 多個線程并發(fā)地完成各自的任務(wù),訪問各自的數(shù)據(jù)資源,而不是共享一份數(shù)據(jù)資源:
public class ThreadDemo extends Thread {
// 數(shù)據(jù)資源
private int ticket = 3;
// 業(yè)務(wù)執(zhí)行邏輯
@Override
public void run() {
for(int i=0;i<3;i++){
if(ticket>0){
System.out.println(Thread.currentThread().getName()+" 賣票--->"+ ticket--);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println(Thread.currentThread().getName()+" 線程運行結(jié)束");
}
public static void main(String[] args) throws InterruptedException {
// 創(chuàng)建2個線程,分別去執(zhí)行線程體中的業(yè)務(wù)邏輯
Thread thread1 = new ThreadDemo();
thread1.start();
Thread thread2 = new ThreadDemo();
thread2.start();
Thread.sleep(1000);
System.out.println("main線程運行結(jié)束");
}
}
多個線程并發(fā)地完成各自的任務(wù),訪問各自的數(shù)據(jù)資源:
Thread-0 賣票--->3 Thread-1 賣票--->3 main線程運行結(jié)束 Thread-0 賣票--->2 Thread-1 賣票--->2 Thread-1 賣票--->1 Thread-0 賣票--->1 Thread-0 線程運行結(jié)束 Thread-1 線程運行結(jié)束
(2) 通過繼承Thread類可以實現(xiàn)資源共享:
public class ThreadTask {
private int ticket = 3;
public synchronized void saleTicket(){
for(int i=0;i<3;i++){
if(ticket>0){
System.out.println(Thread.currentThread().getName()+" 賣票--->"+ticket--);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println(Thread.currentThread().getName()+" 線程運行結(jié)束");
}
}
public class ThreadA extends Thread {
ThreadTask threadTask ;
public ThreadA(ThreadTask threadTask){
super();
this.threadTask = threadTask;
}
@Override
public void run() {
threadTask.saleTicket();
}
}
public class ThreadB extends Thread {
ThreadTask threadTask ;
public ThreadB(ThreadTask threadTask){
super();
this.threadTask = threadTask;
}
@Override
public void run() {
threadTask.saleTicket();
}
}
public class Main {
public static void main(String[] args) throws InterruptedException {
ThreadTask threadTask = new ThreadTask();
ThreadA t1 = new ThreadA(threadTask);
ThreadB t2 = new ThreadB(threadTask);
t1.start();
t2.start();
}
}
執(zhí)行結(jié)果:
Thread-0 賣票--->3
Thread-1 賣票--->2
Thread-1 賣票--->1
Thread-0 線程運行結(jié)束
Thread-1 線程運行結(jié)束
(3) 通過實現(xiàn)Runnable接口實現(xiàn)多線程,能更好地做到多個線程并發(fā)地完成同一個任務(wù),訪問同一份數(shù)據(jù)資源。多個線程的代碼邏輯可以方便地訪問和處理同一個共享數(shù)據(jù)資源 ,這樣可以將線程邏輯和業(yè)務(wù)數(shù)據(jù)進行有效的分離,更好地體現(xiàn)了面向?qū)ο蟮脑O(shè)計思想。
public class RunnableDemo{
public static class RunnableTask implements Runnable{
// 數(shù)據(jù)資源
private int ticket = 3;
// 線程執(zhí)行體
@Override
public synchronized void run() {
for(int i=0;i<3;i++){
if(ticket>0){
System.out.println(Thread.currentThread().getName()+" 賣票--->"+ticket--);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println(Thread.currentThread().getName()+" 線程運行結(jié)束");
}
}
public static void main(String[] args) {
// 將這一個target作為參數(shù)傳給兩個線程,那么這兩個線程執(zhí)行的都是這個target的run()方法
Runnable target = new RunnableTask();
// 創(chuàng)建兩個線程執(zhí)行target的線程體
Thread thread1 = new Thread(target,"thread1");
thread1.start();
Thread thread2 = new Thread(target,"thread2");
thread2.start();
System.out.println("main線程運行結(jié)束");
}
}
多個線程并發(fā)地完成同一個任務(wù),訪問同一份數(shù)據(jù)資源:
main線程運行結(jié)束
thread1 賣票--->3
thread1 賣票--->2
thread1 賣票--->1
thread1 線程運行結(jié)束
thread2 線程運行結(jié)束
3. 可以與線程池配合使用,從而管理線程的生命周期
實現(xiàn)Runnable接口來實現(xiàn)線程,執(zhí)行目標類,更容易和線程池配合使用,異步執(zhí)行任務(wù)在大多數(shù)情況下是通過線程池去提交的,而很少通過創(chuàng)建一個新的線程去提交,所以更多的做法是,通過實現(xiàn)Runnable接口創(chuàng)建異步執(zhí)行任務(wù),而不是繼承Thread去創(chuàng)建異步執(zhí)行任務(wù)。
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
這么設(shè)置IDEA中的Maven,再也不用擔心依賴下載失敗了
今天給大家?guī)硪粋€IDEA中Maven設(shè)置的小技巧.這個技巧可以說非常有用,學會設(shè)置之后,再也不用擔心maven依賴下載變慢的問題,需要的朋友可以參考下2021-05-05
關(guān)于SpringCloud的Bus消息總線圖文詳解
這篇文章主要介紹了關(guān)于SpringCloud的Bus消息總線圖文詳解,Spring Cloud Bus是用來將分布式系統(tǒng)的節(jié)點與輕量級消息系統(tǒng)鏈接起來的框架,它整合了Java的事件處理機制和消息中間件的功能,需要的朋友可以參考下2023-05-05
mybatis實現(xiàn)獲取入?yún)⑹荓ist和Map的取值
這篇文章主要介紹了mybatis實現(xiàn)獲取入?yún)⑹荓ist和Map的取值問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-06-06

