java併發編程之Thread類詳細使用(四)

原博文地址:http://www.cnblogs.com/dolphin0520/p/3920357.html

1.線程的狀態:new(創建)->runnable(就緒)->running(運行),運行時又分狀態:阻塞(blocked),time waiting(睡眠或等待一定的事件),waiting(等待被喚醒)。

線程執行完畢,或者突然中斷,進入dead(死亡or銷燬)狀態。如下圖所示:

2.Thread之sleep()方法:

1)sleep相當於讓線程睡眠,交出CPU,讓CPU去執行其他的任務。

2)sleep方法不會釋放鎖,也就是說如果當前線程持有對某個對象的鎖,則即使調用sleep方法,其他線程也無法訪問這個對象。

例子如下:

public class Threadsleep {
    
	private int i = 10;
    private Object object = new Object();
     
    public static void main(String[] args) throws IOException  {
    	Threadsleep threadsleep = new Threadsleep();
    	//下面兩個線程共享threadsleep對象
        MyThread thread1 = threadsleep.new MyThread();
        MyThread thread2 = threadsleep.new MyThread();
        thread1.start();
        thread2.start();
    } 
     
    class MyThread extends Thread{
        @Override
        public void run() {
            synchronized (object) {
                i++;
                System.out.println("i:"+i);
                try {
                    System.out.println("線程"+Thread.currentThread().getName()+"進入睡眠狀態");
                    Thread.currentThread().sleep(10000);
                } catch (InterruptedException e) {
                    // TODO: handle exception
                }
                System.out.println("線程"+Thread.currentThread().getName()+"睡眠結束");
                i++;
                System.out.println("i:"+i);
            }
        }
    }
	
}

結果:


結論:當Thread-0進入睡眠狀態之後,Thread-1並沒有去執行具體的任務。只有當Thread-0執行完之後,此時Thread-0釋放了對象鎖,Thread-1纔開始執行。

3.Thread之join()方法:

join()
join(long millis)     //參數爲毫秒
join(long millis,int nanoseconds)    //第一參數爲毫秒,第二個參數爲納秒

1)假如在main線程中,調用thread.join方法,則main方法會等待thread線程執行完畢或者等待一定的時間。

2)如果調用的是無參join方法,則等待thread執行完畢,如果調用的是指定了時間參數的join方法,則等待一定的事件。

例子如下:

public class Threadjoin {
    
    public static void main(String[] args) throws IOException  {
        System.out.println("進入線程"+Thread.currentThread().getName());
        Threadjoin threadjoin = new Threadjoin();
        MyThread thread1 = threadjoin.new MyThread();
        thread1.start();
        try {
            System.out.println("線程"+Thread.currentThread().getName()+"等待");
            thread1.join();
            System.out.println("線程"+Thread.currentThread().getName()+"繼續執行");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    } 
     
    class MyThread extends Thread{
        @Override
        public void run() {
            System.out.println("進入線程"+Thread.currentThread().getName());
            try {
                Thread.currentThread().sleep(5000);
            } catch (InterruptedException e) {
                // TODO: handle exception
            }
            System.out.println("線程"+Thread.currentThread().getName()+"執行完畢");
        }
    }
}
結果:

結論:1)當調用thread1.join()方法後,main線程會進入等待。然後等待thread1執行完之後再繼續執行。

2)thread1.join()後讓main線程進入阻塞狀態,並且會釋放線程佔有的鎖,並交出CPU執行權限。

4.Thread之interrupt方法:

1)interrupt,顧名思義,即中斷的意思。

2)單獨調用interrupt方法可以使得處於阻塞狀態的線程拋出一個異常,也就說,它可以用來中斷一個正處於阻塞狀態的線程。

例子如下:

public class Threadinterrupt {

   public static void main(String[] args) throws IOException  {
	Threadinterrupt threadinterrupt = new Threadinterrupt();
        MyThread thread = threadinterrupt.new MyThread();
        thread.start();
        try {
            Thread.currentThread().sleep(2000);
        } catch (InterruptedException e) {
             
        }
        thread.interrupt();
    } 
     
    class MyThread extends Thread{
        @Override
        public void run() {
            try {
                System.out.println("進入睡眠狀態");
                Thread.currentThread().sleep(10000);
                System.out.println("睡眠完畢");
            } catch (InterruptedException e) {
                System.out.println("得到中斷異常");
            }
            System.out.println("run方法執行完畢");
        }
    }
	
}
結果:

結論:1)interrupt方法可以中斷處於阻塞狀態的線程。

問題:interrupt能不能中斷處於非阻塞狀態的線程呢?如下例子:

public class Threadinterrupt2 {

   public static void main(String[] args) throws IOException  {
	Threadinterrupt2 threadinterrupt2 = new Threadinterrupt2();
        MyThread thread = threadinterrupt2.new MyThread();
        thread.start();
        try {
            Thread.currentThread().sleep(2000);
        } catch (InterruptedException e) {
             
        }
        thread.interrupt();
    } 
     
    class MyThread extends Thread{
        @Override
        public void run() {
            int i = 0;
            while(i<Integer.MAX_VALUE){
                System.out.println(i+" while循環");
                i++;
            }
        }
    }
	
}

結論:通過測試結果,發現直接調用interrupt方法不能中斷正在運行中的線程

問題:如何中斷正在運行的線程呢?

1)一般會在MyThread類中增加一個屬性 isStop來標誌是否結束while循環,然後再在while循環中判斷isStop的值。如下:

class MyThread extends Thread{
        private volatile boolean isStop = false;
        @Override
        public void run() {
            int i = 0;
            while(!isStop){
                i++;
            }
        }
         
        public void setStop(boolean stop){
            this.isStop = stop;
        }
    }

那麼就可以在外面通過調用setStop方法來終止while循環。

5.Thread其他方法:

1)getId 用來得到線程ID。

2)getName和setName。用來得到或者設置線程名稱。

3)getPriority和setPriority。用來獲取和設置線程優先級。

4)setDaemon和isDaemon。用來設置線程是否成爲守護線程和判斷線程是否是守護線程。

5)currentThread()。常用,用來獲取當前線程。

演示關係圖如下:


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章