![](/img/trans.png)
[英]Thread.sleep method called inside main method, what thread would it pause?
[英]Pause Thread after a method is called
基本上,我想在調用方法后暫停線程,然后再繼續執行另一個方法。 我無法循環,我的方法只能運行一次。 其背后的想法是在游戲中使用,該方法將顯示消息,並且每當用戶按下一個鍵時,就會顯示下一條消息。 我不能只瀏覽列表,因為游戲需要用戶輸入。 我看了看Thread.pause()
和Thread.resume()
但它們都不起作用,並且已被棄用。 我目前的程式碼(無法運作):
private Thread thread;
private Thread managerThread;
private final Object lock = new Object();
private boolean shouldThreadRun = true;
private boolean storyRunning = true;
public Storyline() {
setUpThread();
}
private void setUpThread() {
managerThread = new Thread(() -> {
while(storyRunning) {
synchronized (lock) {
if(!shouldThreadRun) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("Looping");
}
}
});
thread = new Thread(() -> {
synchronized (lock) {
pauseThread();
System.out.print("A");
pauseThread();
System.out.print("B");
}
});
managerThread.start();
thread.start();
}
public void pauseThread() {
shouldThreadRun = false;
}
public void resumeThread() {
shouldThreadRun = true;
}
查看我的修改,看看它是否與您要實現的內容相似。 我正在使用掃描儀來模擬用戶輸入,只需按鍵盤上的Enter即可嘗試。 順便說一句,我希望這只是一種鍛煉,而不是現實生活中的情況。 除非確實有必要,否則您應嘗試避免在實際產品中進行這種低級別的多線程管理,在這種情況下,您仍應使用為此目的使用的適當數據結構。 在實際的應用程序中,按鈕將鏈接到回調,並且您將設置一些onClick()方法以在按下按鈕后立即執行所需的代碼。
關於並發,我強烈建議您看一下這些教程: Oracle-Concurrency
PS:請注意,我完全忽略了中斷,這是一種不好的做法,應該以正確的方式處理這些異常:我只是試圖通過使代碼盡可能簡單來實現所需的結果。 另外,就像其他人指出的那樣,您應該通過在循環內調用wait來處理虛假喚醒。
private Thread thread;
private Thread managerThread;
private final Object lock = new Object();
Scanner in;
public Storyline() {
setUpThread();
}
private void setUpThread() {
managerThread = new Thread(() -> {
while(true) {
in = new Scanner(System.in);
in.nextLine();
resumeThread();
}
});
thread = new Thread(() -> {
synchronized (lock) {
while(true){
System.out.print("A");
try {
lock.wait();
} catch (InterruptedException e) {}
System.out.print("B");
try {
lock.wait();
} catch (InterruptedException e) {}
}
}
});
managerThread.start();
thread.start();
}
public void resumeThread() {
synchronized(lock){
lock.notify();
}
}
如文檔中所述 ,Object.wait的第一條規則是必須在循環中調用該規則,該循環取決於等待的基礎條件。
因此,您的等待需要看起來像這樣:
synchronized (lock) {
while (!shouldThreadRun) {
lock.wait();
}
}
中斷不是偶然發生的事情。 僅當另一個線程明確要求它停止正在執行的操作並干凈地退出時,該線程才會被中斷。
因此,如果收到中斷,則正確的做法是不要忽略該中斷並打印堆棧跟蹤。 您需要干凈地退出。
最簡單的方法是將整個while循環包含在try / catch中:
try {
while (storyRunning) {
synchronized (lock) {
while (!shouldThreadRun) {
lock.wait();
}
System.out.println("Looping");
}
}
} catch (InterruptedException e) {
System.out.println("Exiting, because someone asked me to stop.");
e.printStackTrace();
}
這樣,您的while循環將在被中斷時自動退出。
最后,除非另一個線程在與等待線程同步的同一對象上調用Object.notify或Object.notifyAll,否則Object.wait是無用的。 除非對象得到通知,否則wait方法可能不會返回:
public void pauseThread() {
synchronized (lock) {
shouldThreadRun = false;
// Tell waiting thread that shouldThreadRun may have changed.
lock.notify();
}
}
public void resumeThread() {
synchronized (lock) {
shouldThreadRun = true;
// Tell waiting thread that shouldThreadRun may have changed.
lock.notify();
}
}
請注意,同步在方法內部。 如果您一直保持線程同步在lock
狀態,則管理器線程將永遠不會有運行的機會,因為它試圖獲取同一對象的同步鎖定。 (但是,相反的情況並非如此;管理器線程可以一直保持lock
同步,因為wait()方法將暫時釋放同步鎖,從而允許另一個線程繼續執行。)
如果所有訪問shouldThreadRun
代碼都在同步塊內部,則無需(也不應)使shouldThreadRun
易變,因為同步已經確保了多線程的一致性。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.