在java中使用另一个线程的输入退出一个线程的无限等待
我正在制作一个Java应用程序,它在热键组合上做一些事情。我有一个无限的while循环来等待热键输入关闭,但这使得应用程序非常耗费CPU时间 以下是我的代码最简单的外观:在java中使用另一个线程的输入退出一个线程的无限等待,java,multithreading,infinite-loop,hotkeys,Java,Multithreading,Infinite Loop,Hotkeys,我正在制作一个Java应用程序,它在热键组合上做一些事情。我有一个无限的while循环来等待热键输入关闭,但这使得应用程序非常耗费CPU时间 以下是我的代码最简单的外观: static boolean isOpen = true; void main() { .... add SomeHotKeyListener(); .... while(isOpen) { } releaseResources(); } void onHotKey(int
static boolean isOpen = true;
void main()
{
....
add SomeHotKeyListener();
....
while(isOpen)
{ }
releaseResources();
}
void onHotKey(int hotKeyIdentifier)
{
if(hotKeyIdentifier == something)
do something;
if(hotKeyIdentifier == something)
isOpen = false;
}
我需要一种多线程方法来实现这一点,或者如果有人有更好的方法来适应。我建议您阅读Java中的
synchronized
关键字。只是,你应该找到大量的例子
这将解决您的问题:
static boolean isOpen = true;
static Object lock = new Object();
void main()
{
....
add SomeHotKeyListener();
....
synchronized(lock)
{
while(isOpen)
{
try {
lock.wait()
} catch(InterruptedException e) {
}
}
}
releaseResources();
}
void onHotKey(int hotKeyIdentifier)
{
if(hotKeyIdentifier == something)
do something;
if(hotKeyIdentifier == something)
{
synchronized(lock)
{
isOpen = false;
lock.notify();
}
}
}
无限while循环会消耗大量的系统资源。建议使用等待和通知。此外,还必须声明布尔
volatile
,否则无法保证一个线程所做的更改会被另一个线程拾取。下面是一个示例,它在一个单独的线程中执行某些操作,直到被基于用户输入的调用线程中断(在本例中为enter)。另请参见Oracle的示例
非常感谢你的回答。这正是我们需要的,没问题。但是我忘记了一件事(zencv在他/她的回复中提到了这件事),那就是使
isOpen
易失性,这对于确保引用该变量时两个线程访问相同的内存是非常重要的,如前所述。在这种情况下,需要使用易失性变量是什么,由于您先前在同步块中等待和通知的解决方案足以满足需要,我撤销了先前的评论。您是正确的,因为使用同步块与同一对象上的任何其他同步块建立了关系,从而使同步块内的所有更改可以从同一对象上的任何其他同步块访问。我在Oracle文档中阅读了以下行:当同步方法退出时,它会自动与同一对象的同步方法的任何后续调用建立“发生在之前”关系。这保证了对对象状态的更改对所有线程都是可见的“。找到来源。对于相同的线程使用是否需要使用volatile变量而不是其他线程使用?在这种情况下,实际上需要使用volatile
关键字。原因是有这样一种情况,shutdown
可以从两个线程同时访问,而没有其他防御机制。这发生在run()
函数的第一行。如果对shutdown
的所有访问都在同步代码中,则不需要这样做。请注意,在我的回答中,我通过将而(!shutdown)
放在同步块中解决了这个问题。如果希望只调用一次封装函数main()
,我的解决方案会更好。如果希望多次调用封装函数run()
,zencv的解决方案会更好(因为在后续调用中,它会立即将shutdown
标识为true
,并且根本不需要输入同步代码。请记住,输入同步代码会产生成本)。
import java.util.Scanner;
public class WaitTest implements Runnable {
private volatile boolean shutdown = false;
public static void main(String[] args) {
WaitTest w = new WaitTest();
new Thread(w).start();
System.out.println("Press any key to interrupt");
Scanner sc = new Scanner(System.in);
sc.nextLine();
w.triggerShutDown();
}
@Override
public void run() {
while (!shutdown) {
synchronized (this) {
try {
System.out.println("doing some silly things");
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
System.out.println("Server shutdown successfully");
}
public synchronized void triggerShutDown() {
this.shutdown = true;
notify();
}
}