天天看點

java 暫停_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)