Thread和Runnable的區別


轉自:https://www.cnblogs.com/soaringEveryday/p/4290725.html

 

1.  首先是使用上的區別,先看代碼:

復制代碼
class MyThread extends Thread
{
    @Override
    public void run() {
        System.out.println("do things");
    }
}

class MyRunnable implements Runnable
{

    @Override
    public void run() {
        System.out.println("do things");
        
    }
}
復制代碼

可以看到使用Thread是繼承關系,而使用Runnable是實現關系。我們知道java不支持多繼承,如果要實現多繼承就得要用implements,所以使用上Runnable更加的靈活

 

2. 關於共享數據的問題

Runnable是可以共享數據的,多個Thread可以同時加載一個Runnable,當各自Thread獲得CPU時間片的時候開始運行runnable,runnable里面的資源是被共享的

這里用實例來講解:

首先分別定義一個thread和一個runnable,things這個變量即為所想要共享的資源

復制代碼
class MyThread extends Thread
{
    int things = 5;
    @Override
    public void run() {
        while(things > 0)
        {
            System.out.println(currentThread().getName() + " things:" + things);
            things--;
        }
    }
}

class MyRunnable implements Runnable
{
    String name;
    
    public MyRunnable(String name)
    {
        this.name = name;
    }
    
    int things = 5;
    @Override
    public void run() {
        while(things > 0)
        {
       things--;
System.out.println(name + " things:" + things); } } }
復制代碼

隨后,用三個Thread來運行看:

復制代碼
public class ThreadTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        
        MyThread thread1 = new MyThread();
        MyThread thread2 = new MyThread();
        MyThread thread3 = new MyThread();
        thread1.start();
        thread2.start();
        thread3.start();
        
    }

}
復制代碼

結果如下:

復制代碼
Thread-0 things:5
Thread-0 things:4
Thread-2 things:5
Thread-1 things:5
Thread-1 things:4
Thread-1 things:3
Thread-1 things:2
Thread-1 things:1
Thread-2 things:4
Thread-2 things:3
Thread-2 things:2
Thread-2 things:1
Thread-0 things:3
Thread-0 things:2
Thread-0 things:1
復制代碼

可以看到每個Thread都是5個things,所以資源是不共享的

下面用一個Runnable在3個Thread中加載嘗試看看:

 

復制代碼
public class ThreadTest {

    /**
     * @param args
     */
    public static void main(String[] args) {
        
        MyRunnable run = new MyRunnable("run");
        Thread th1 = new Thread(run, "Thread 1");
        Thread th2 = new Thread(run, "Thread 2");
        Thread th3 = new Thread(run, "Thread 3");

        th1.start();
        th2.start();
        th3.start();
        
    }

}
復制代碼

結果如下:

run things:3
run things:2
run things:1
run things:0
run things:3

一共打印出了5次,表示things資源使用了5次

 

3、線程Thread的5狀態

創建:執行new方法創建對象,即進入創建狀態

就緒:創建對象后,執行start方法,即被加入線程隊列中等待獲取CPU資源,這個時候即為就緒狀態

運行:CPU騰出時間片,該thread獲取了CPU資源開始運行run方法中的代碼,即進入了運行狀態

阻塞:如果在run方法中執行了sleep方法,或者調用了thread的wait/join方法,即意味着放棄CPU資源而進入阻塞狀態,但是還沒有運行完畢,帶重新獲取CPU資源后,重新進入就緒狀態

停止:一般停止線程有兩種方式:1執行完畢run方法,2調用stop方法,后者不推薦使用。可以在run方法中循環檢查某個public變量,當想要停止該線程時候,通過thread.para為false即可以將run提前運行完畢,即進入了停止狀態

 

4、線程分類

a. 用戶線程,比如主線程,連接網絡的線程

b. 守護線程,運行在后台,為用戶線程服務 Thread.setDeamon,必須在start方法前調用。守護線程里面不能做一寫IO讀寫的操作。因為當用戶線程都結束后,守護線程也會隨jvm一起被銷毀,如果這個時候守護線程里面還有IO未完成的操作,就會崩潰


免責聲明!

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



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