Java執行緒休眠方法sleep、執行緒讓步yield和join方法
執行緒休眠(sleep方法)
執行緒休眠:讓執行緒暫緩執行,等到預計時間之後再恢復執行。
執行緒休眠會交出cpu,讓cpu去執行其他任務,但是不會釋放鎖。
比如:當前執行緒sleep休眠了,但是如果此執行緒在休眠前持有某個物件的鎖,那就算它休眠了其他執行緒也不能獲取到這個物件的鎖。
注意:呼叫sleep結束後執行緒會重新回到就緒狀態,只需要等待獲取cpu執行就可以。
方法:
public static native void sleep(long millis) throws InterruptedException
休眠的時間是以毫秒為單位
使用:
class MyThread implements Runnable{ @Override public void run() { for(int i = 0; i < 5; i++){ try { sleep(2000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+" i=" + i); } } } public class Test{ public static void main(String[] args){ MyThread myThread = new MyThread(); new Thread(myThread).start(); new Thread(myThread).start(); new Thread(myThread).start(); } }
執行緒讓步(yield()方法)
yield():暫停當前正在執行的執行緒物件,並執行其他執行緒。
執行緒讓步會交出cpu許可權,讓cpu去執行其他的執行緒。和sleep方法類似,同樣不會釋放鎖,但是yield不能控制具體交出cpu的時間,並且,yield方法只能讓擁有相同優先順序的執行緒有獲取cpu執行的機會。
注意:呼叫yield結束後執行緒會重新回到就緒狀態,只需要等待獲取cpu執行就可以。
使用:
class MyThread implements Runnable{ @Override public void run() { for(int i = 0; i < 5; i++){ Thread.yield(); System.out.println(Thread.currentThread().getName()+" i=" + i); } } } public class Test{ public static void main(String[] args){ MyThread myThread = new MyThread(); new Thread(myThread).start(); new Thread(myThread).start(); new Thread(myThread).start(); } }
等待其他執行緒終止-join()方法
意思就是說如果在主執行緒中呼叫這個方法時會讓主執行緒休眠,讓呼叫該方法的執行緒run方法先執行完畢後再開始執行主執行緒。
join放發實際上是對wait方法的封裝。
我們來看join的原始碼
public final void join() throws InterruptedException {
join(0);
}
我們可以看到join方法實際上是呼叫了join(0);
join(long millis)方法如下:
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
從上面我們可以提取出join(0)呼叫的部分程式碼;如下:
if (millis == 0) {
while (isAlive()) {//判斷當前執行緒是否為Running狀態
wait(0);
}
從上面可以看出如果呼叫此方法的執行緒是正在執行的執行緒,那麼就會呼叫wait(0)方法,
關於wait()的原始碼:
public final native void wait(long timeout) throws InterruptedException;
wait(long timeout)是一個本地方法,呼叫本機的原生系統函式,當Thread類被載入到JVM中的時候,它就會呼叫註冊相應的本地方法。
wait(0)就是讓其他執行緒一直在等待,當此執行緒終止時,會呼叫執行緒自身的notifyAll()方法,喚醒所有等待在該執行緒物件上的執行緒。
使用:
public class Test{
public static void main(String[] args) throws InterruptedException {
final Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t1");
}
});
final Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t2");
}
});
final Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t3");
}
});
t1.start();
t3.start();
t2.start();
}
}
執行結果:
t1
t2
t3
當t2比t3start時間遲的時候,出現下面結果
public class Test{
public static void main(String[] args) throws InterruptedException {
final Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t1");
}
});
final Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t2");
}
});
final Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t3");
}
});
t1.start();
t3.start();
Thread.sleep(2000);//讓主執行緒休眠2秒,那麼在t3呼叫join時t2還不是執行狀態
t2.start();
}
}
執行結果如下:
t1
t3
t2
這就是因為join(0)中呼叫了
if (millis == 0) {
while (isAlive()) {//判斷當前執行緒是否為Running狀態
wait(0);
}
因為t2不處於執行狀態所以不會執行wait(0),所以t3就不會等待,直接執行下一條語句。