[英]while loop not looping / displaying count
此方法反復讀取命令並執行它們,直到游戲結束。 Finished變量為true時,表示玩家/用戶已按下Quit並想要結束游戲-因此退出循環並執行到方法結束。
import org.apache.commons.lang3.time.StopWatch;
private Parser parser;
private Command command;
private StopWatch stopWatch;
public void play()
{
stopWatch = new StopWatch();
stopWatch.start();
long timeLimit = 5000;
boolean finished = false;
printWelcome();
while (finished == false)
{
System.out.println(stopWatch.getTime() + " milliseconds");
if (stopWatch.getTime() >= timeLimit)
{
System.out.println("Time limit of " + timeLimit + " milli seconds has been reached. Good bye!");
return;
}
else
{
command = parser.getCommand();
finished = processCommand(command);
}
}
System.out.println("Thank you for playing. Good bye.");
}
但是我正在觀察循環的奇怪行為。 循環非常好(省略以下幾行時,顯示stopWatch.getTime()的連續計數:
else
{
command = parser.getCommand();
finished = processCommand(command);
}
但是當我把它們放回去時,它會停止顯示stopWatch的連續遞增時間,因為它朝着timeLimit遞增(此時,它應該停止)。 即使播放器沒有輸入任何命令或輸入。
秒表顯然在后台運行,但是不顯示計數。
請指教。 謝謝。
即使播放器沒有輸入任何命令或輸入。
如果Parser#getCommand
是等待用戶輸入的方法,則執行將阻塞,直到用戶輸入輸入為止。 這意味着while
循環將不會運行,並且您不會看到它打印出新的時間。
無論如何,執行您要求的操作都會給用戶帶來非常刺耳的體驗,因為這將意味着在用戶鍵入命令時它將繼續打印,並且這不是非常用戶友好的。
您可以為此使用生產者-消費者方法 。 我已經根據鏈接的問題改編了代碼:
// Shared queue
final Queue<String> commands = new ConcurrentLinkedQueue<>();
// Non-blocking consumer
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
executor.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
// non-blocking
if((String command = commands.poll()) != null) {
processCommand(command);
}
}
}, 0, 10, TimeUnit.MILLISECONDS);
// Blocking producer (this is basically the logic from Parser#getCommand)
Scanner sc = new Scanner(System.in);
while(sc.hasNext()) {
commands.add(sc.next());
}
但是,此解決方案並不能真正讓您實現超時。 因此,您將必須創建一個新類來“包裝” Runnable
以便在超時后可以將其取消(類似於此方法):
public class TimeOutableRunnable implements Runnable {
private final Queue<String> commands;
private final Runnable wrapped;
private volatile ScheduledFuture<?> self;
public TimeOutableRunnable(Runnable wrapped, Queue<String> commands) {
this.commands = commands;
this.wrapped = wrapped;
}
@Override
public void run() {
if(commands.isEmpty()) {
self.cancel(false);
} else {
wrapped.run();
}
}
public void runWithTimeout(ScheduledExecutorService executor, long timeout, TimeUnit unit) {
self = executor.scheduleAtFixedRate(this, 0, timeout, unit);
}
}
然后,您可以執行以下操作:
final Queue<String> commands = new ConcurrentLinkedQueue<>();
ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor();
new TimeOutableRunnable(new Runnable() {
@Override
public void run() {
// non-blocking
while((String command = commands.poll()) != null) {
processCommand(command);
}
}
}, commands).runWithTimeout(executor, timeLimit, TimeUnit.MILLISECONDS);
我還沒有對此進行測試,因此我對並發性評價不高,所以請告訴我這種方法是否存在根本性的錯誤。
我假設您的parser.getCommand();
在輸入之前一直處於阻塞狀態。 當while循環在一個線程中運行時,程序將在此時停止。
檢查我是否正確的最簡單方法是輸入任何命令,並且您應該從此行獲得一些輸出:
System.out.println(stopWatch.getTime() + " milliseconds");
您或者需要在此方法中實現超時,或者需要第二個線程對時間進行計數並中斷等待。
也許我誤會了您的問題,但是聽起來好像您的問題是它不是連續打印的? 如果是這樣,那是因為您的解析器正在等待用戶輸入。 線程可以解決此問題,運行計時器並在單獨的線程中打印
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.