Runnable和Thread區別和比較


在很多博客中用這樣一個例子來說明

  Runnable更容易實現資源共享,能多個線程同時處理一個資源。

看代碼:

public static void main(String[] args) {  
              
            new MyThread().start();  
            new MyThread().start();  
              
    }  
  
class MyThread extends Thread{    
    private int ticket = 5;    
    public void run(){    
         while(true){  
             System.out.println("Thread ticket = " + ticket--);    
             if(ticket < 0){    
                break;  
             }    
         }    
    }    
}   

輸出結果:

Thread ticket = 5  
Thread ticket = 5  
Thread ticket = 4  
Thread ticket = 4  
Thread ticket = 3  
Thread ticket = 2  
Thread ticket = 3  
Thread ticket = 1  
Thread ticket = 2  
Thread ticket = 0  
Thread ticket = 1  
Thread ticket = 0

  這樣多賣了一半的票顯然不合理,用runnable試試:

public static void main(String[] args) {  
        // TODO Auto-generated method stub  
        MyThread2 m=new MyThread2();  
            new Thread(m).start();  
            new Thread(m).start();  
              
    }  
class MyThread2 implements Runnable{    
    private int ticket = 5;    
    public void run(){    
         while(true){  
             System.out.println("Runnable ticket = " + ticket--);    
             if(ticket < 0){    
                break;  
             }    
         }   
    }    
}

輸出結果:

Runnable ticket = 5  
Runnable ticket = 4  
Runnable ticket = 3  
Runnable ticket = 2  
Runnable ticket = 1  
Runnable ticket = 0  

  這樣的結果才合理。
  很明顯這個例子完全錯誤,多賣票的原因根本不是因為Runnable和Thread的區別,看調用就知道了。
  使用Thread的時候是這樣調用的:  

new MyThread().start();  
new MyThread().start(); 

  而使用Runnable的時候是這樣調用的:

new Thread(m).start();  
new Thread(m).start();

  新建了兩個MyThread對象去賣票,不賣兩倍票才怪呢,而Runnable賣票的時候是同一個Runnable對象,肯定只賣一倍票,所以這個例子根本沒體現Runnable和Thread的區別,再來看一個例子:

public class TicketThread extends Thread{

    private int ticket = 10;

    public void run(){
        for(int i =0;i<10;i++){
            synchronized (this){
                if(this.ticket>0){
                    try {
                        Thread.sleep(100);
                        System.out.println(Thread.currentThread().getName()+"賣票---->"+(this.ticket--));
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    public static void main(String[] arg){
        TicketThread t1 = new TicketThread();
        new Thread(t1,"線程1").start();
        new Thread(t1,"線程2").start();
    }
}

輸出結果:

線程1賣票—->10 
線程1賣票—->9 
線程1賣票—->8 
線程2賣票—->7 
線程2賣票—->6 
線程1賣票—->5 
線程1賣票—->4 
線程2賣票—->3 
線程2賣票—->2 
線程1賣票—->1

  (這里必須使用synchronized,否則會出現重復賣某一張票的情況,當然這點和本篇文章無關,這里不做詳述。)
  這樣就達到了賣一倍票的結果,沒毛病。這樣看起來,Thread和Runnable豈不是沒區別了?
  找到答案很簡單,點進去看Thread源碼就知道了

public class Thread implements Runnable {}

  可以看出,Thread實現了Runnable接口,這和上面例子中的MyThread2一樣了,當我們使用

TicketThread t1 = new TicketThread();
new Thread(t1,"線程1").start();

  這種寫法時,會被認為智障。。。。沒錯,就是智障,這是脫褲子放屁的寫法,標准寫法應該是:

TicketThread t1 = new TicketThread();
t1.start();

  看看源碼:

public Thread(Runnable target) {
        init(null, target, "Thread-" + nextThreadNum(), 0);
    }
  new Thread( new TicketThread(),"線程1").start();這種寫法里面,TicketThread會被當做一個Runnable,那我還要寫一個TicketThread類干嘛?所以這就是脫褲子放屁。
  說了這么多,那兩者的區別到底是什么?
  來看看Runnable的代碼:
public interface Runnable {
    /**
     * When an object implementing interface <code>Runnable</code> is used
     * to create a thread, starting the thread causes the object's
     * <code>run</code> method to be called in that separately executing
     * thread.
     * <p>
     * The general contract of the method <code>run</code> is that it may
     * take any action whatsoever.
     *
     * @see     java.lang.Thread#run()
     */
    public abstract void run();
}

結論就是:

  1、效果上沒區別,寫法上的區別而已。
  2、沒有可比性,Thread實現了Runnable接口並進行了擴展,我們通常拿來進行比較只是寫法上的比較,而Thread和Runnable的實質是實現的關系,不是同類東西。
 
  無論你使用Runnable還是Thread,都有一個new Thread的過程,效果上最后都是new Thread,然后執行run方法。寫法上的區別無非就是你是new Thead還是new你自定義的thread,如果你有復雜的線程操作需求,那就自定義Thread,如果只是簡單的在子線程run一下任務,那就自己實現runnable,當然如果自己實現runnable的話可以多一個繼承(自定義Thread必須繼承Thread類,java單繼承規定導致不能在繼承別的了)。


鏈接:https://www.jianshu.com/p/9c9a11092f26


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM