休眠
在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)