Java多線程程序休眠、暫停與停止


休眠

  在Java多線程中,可以使用sleep()方法在指定毫秒數內讓當前正在執行的線程休眠。
  下面這段代碼,使得主函數的main線程休眠了2000ms,最后輸出的間隔時間也是2000ms。

public class MyThread extends Thread {
    public static void main(String[] args) {
        try {
            long begin;
            long end;
            begin = System.currentTimeMillis();
            System.out.println("begin = " + begin);
            Thread.sleep(2000);
            end = System.currentTimeMillis();
            System.out.println("end = " + end);
            System.out.println("end - begin = " + (end - begin) + "ms");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

輸出結果:

begin = 1486711105366
end = 1486711107366
end - begin = 2000ms

暫停

  雖然suspend和resume方法可以分別使得線程暫停和回復,但是這兩個方法因為有缺點而已經被棄用。

缺點:

  • 獨占:在使用suspend和resume方法時,如果使用不當,極易造成公共的同步對象獨占,使得其他線程無法訪問公共同步對象。
  • 不同步:在使用suspend與resume方法時也容易因為線程而導致數據不同步的情況。

yield方法

  可以使用yield方法進行暫停。
  yield()方法的作用是放棄當前的CPU資源,將它讓給其他任務去占用CPU執行時間。但放棄的時間不確定,有可能剛剛放棄,馬上又獲得CPU時間片。

public class MyThread extends Thread {
    @Override
    public void run() {
        long beginTime = System.currentTimeMillis();
        int count = 0;
        for (int i = 0; i < 50000000; i++) {
            //Thread.yield();
            count = count + (i + 1);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("用時: " + (endTime - beginTime) + "ms");
    }

    public static void main(String[] args) {
        MyThread myThread = new MyThread();
        myThread.start();
    }
}

輸出結果:

用時: 21ms

  去掉注釋//Thread.yield()后。

輸出結果:

用時: 4471ms

  從第二次輸出可以看出,用時明顯變長。

停止

  雖然stop()可以停止一個線程,但是這個方法是不安全的,而且是已經被棄用作廢的,最好不要使用它。

interrupt()方法

  interrupt()方法的使用效果並不像for+break語句那個,馬上就停止循環。調用interrupt()方法僅僅是在當前線程中打了一個停止的標記,並不是真正停止線程。

判斷線程是否是停止狀態

  • this.interrupted():測試當前線程是否已經是中斷狀態,執行后具有將狀態標志清楚為false的功能,為static方法。
  • this.isInterrupted():測試線程Thread對象是否已經是中斷狀態,但是不清除狀態標志。
public class MyThread extends Thread {
    public static void main(String[] args) {
        Thread.currentThread().interrupt();
        System.out.println("是否停止1? " + Thread.interrupted());
        System.out.println("是否停止2? " + Thread.interrupted());
        System.out.println("end");
    }
}

輸出結果:

是否停止1? true
是否停止2? false
end

public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 50000; i++) {
            System.out.println(i);
        }
    }

    public static void main(String[] args) {
        try {
            MyThread myThread = new MyThread();
            myThread.start();
            Thread.sleep(1000);
            myThread.interrupt();
            System.out.println("是否停止1? " + myThread.isInterrupted());
            System.out.println("是否停止2? " + myThread.isInterrupted());
            System.out.println("end");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

輸出結果(末尾):

49997
49998
49999
是否停止1? false
是否停止2? false
end

能停止線程的方法

  在run中加一個判斷,如果停止了,則break跳出循環體。

public class MyThread extends Thread {
    @Override
    public void run() {
        for (int i = 0; i < 50000000; i++) {
            if (this.interrupted()) {
                System.out.println("已經是停止狀態了,我要退出了");
                break;
            }
            System.out.println(i);
        }
    }

    public static void main(String[] args) {
        try {
            MyThread myThread = new MyThread();
            myThread.start();
            Thread.sleep(1000);
            myThread.interrupt();
            System.out.println("end");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

輸出結果(末尾):

160560
160561
160562
160563
160564
end
已經是停止狀態了,我要退出了

  上述代碼雖然可以停止線程,但是如果for的后面還有語句,那么還是會繼續執行。
  因此可以用下述方法來解決。

public class MyThread extends Thread {
    @Override
    public void run() {
        try {
            for (int i = 0; i < 50000000; i++) {
                if (this.interrupted()) {
                    System.out.println("已經是停止狀態了,我要退出了");
                    throw new InterruptedException();
                }
                System.out.println(i);
            }
            System.out.println("for結束");
        } catch (InterruptedException e) {
            System.out.println("進入run中的catch了");
            e.printStackTrace();
        }

    }

    public static void main(String[] args) {
        try {
            MyThread myThread = new MyThread();
            myThread.start();
            Thread.sleep(1000);
            myThread.interrupt();
            System.out.println("end");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

輸出結果(末尾):

152891
152892
152893
152894
end
已經是停止狀態了,我要退出了
進入run中的catch了
java.lang.InterruptedException
at mythread.MyThread.run(MyThread.java:13)


免責聲明!

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



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