我是Java的新手,我正在尝试使用一个Thread来完成另一个Thread中的循环而不管循环的状态。
public static void main(String[] args) {
// Either start the other thread here
while(true){
// Or here, not quite sure
// Do stuff
}
}
}
public class Timer implements Runnable{
@Override
public void run() {
long start = System.currentTimeMillis();
while(true) {
long current = System.currentTimeMillis();
if(current - start == 10000){
// How do I notify the loop in main to break?
break;
}
}
}
}
我想要做的是在10秒后在main中结束循环,无论其循环状态如何,因为循环包含来自Scanner
的{{1}}读数,并且需要在之后停止无论键盘读取了什么,都是10秒。我认为最好的解决方案是让计时器Thread运行,计算秒数,然后在10秒后以某种方式通知另一个Thread中的循环,但是,我不知道如何实现这个... < / p>
答案 0 :(得分:3)
如果您的目标是在10秒后停止循环,则没有理由使用其他线程。只需在当地检查时间:
public class Main {
public static void main(String[] args) {
// Instructions
long start = System.currentTimeMillis();
do {
//Instructions
//Instructions
//...
//Instructions
} while (System.currentTimeMillis() - start < 10000);
}
}
答案 1 :(得分:2)
这样的事情怎么样:
public static void main(String[] args) {
// Instructions
AtomicBoolean shouldStop = new AtomicBoolean(false);
Timer timer = new Timer(shouldStop);
// start the timer thread
while(true){
if (shouldStop.get()) {
break;
}
//Instructions
}
}
}
public class Timer implements Runnable{
private final AtomicBoolean shouldStop;
public Timer(AtomicBoolean shouldStop) {
this.shouldStop = shouldStop;
}
@Override
public void run() {
long start = System.currentTimeMillis();
while(true){
long current = System.currentTimeMillis();
if(current - start == 10000) {
shouldStop.set(true);
break;
}
}
}
}
答案 2 :(得分:2)
解决问题最安全的方法是使用volatile变量:
public class Main {
private static volatile boolean keepRunning = false;
public static void main(String[] args) {
keepRunning = true;
while(keepRunning) {
//Instructions
//...
//Instructions
}
}
}
public class Timer implements Runnable {
@Override
public void run() {
long start = System.currentTimeMillis();
while(true){
long current = System.currentTimeMillis();
if(current - start == 10000){
// Notify the loop in Main to break
keepRunning = false;
break;
}
}
}
}
答案 3 :(得分:2)
不要重新发明轮子。使用ExecutorService
和get()
超时:
ExecutorService executor = Executors.newSingleThreadExecutor();
// Here's a lambda, but you could use an instance of a normal Runnable class
Runnable runnable = () -> {
while(true){
// Do stuff
}
};
Future<?> future = executor.submit(runnable);
try {
future.get(10, TimeUnit.SECONDS);
} catch (TimeoutException e) {
// the task timed out
future.cancel(true); // this will kill the running thread
} catch (InterruptedException | ExecutionException e) {
// the runnable exploded
}
答案 4 :(得分:0)
有很多解决方案。这是其中之一:
public class Main {
public static void main(String... args) {
Thread thread = () -> {
while(true) {
// We call Thread.interrupted to check the interrupted status of the Thread.
// This method also clears the interrupted status of the Thread.
if(Thread.interrupted()) {
break;
}
// code...
}
}
Thread timer = () -> {
long start = System.currentTimeMillis();
while(true) {
long current = System.currentTimeMillis();
if(current - start == 10_000){ // underscore for clarity
// This causes the thread to interrupt. The next pass
// in our loop in "thread" will first check its interrupted status
// before continuing, and will break if the status is interrupted
thread.interrupt();
break;
}
}
}
// wrap in synchronized block to ensure both threads run simultaneously
synchronized(Main.class) {
thread.start();
timer.start();
}
}
}
在此解决方案中,我们使用 interrupts 来使thread
中的while循环中断。中断在正在执行的任何点停止正常的线程操作,但前提是线程调用抛出InterruptedException
的方法,并且线程在catch块中返回(或中断)。 Thread.interrupt()
将interrupt status设置为中断,但实际上不会中断线程的执行。中断后再次调用run
thread
方法。由于我们在循环开始时检查Thread.interrupted()
,因此循环进入时循环将中断,并且run
退出并且线程停止运行。使用Thread.interrupted()
时,您必须在同一个线程中检查其中断状态,然后选择清除状态时要执行的操作。
作为旁注,如果循环中我们唯一的分支(if语句)检查该线程的中断状态,那么如果我们简单地将while循环声明为{,那么它可能更容易阅读并且更有效率{1}}。否则它应保持不变。
其他解决方案在这里通过其他一些答案进行说明,但有些解决方案以不同的方式解答整个问题。其他一些解决方案包括使用Oliver Dain回答的AtomicBoolean;另一个使用全局lock object和易失性布尔值或AtomicBoolean。
有许多解决方案,但在大多数用例中,中断解决方案似乎是最简单和最方便的。