以下代码段是名为“Foo”的线程,它休眠1分钟,然后将 1分钟中键入的数据复制到日志文件中。
while(isStarted) {
try {
Thread.sleep(60000); // sleep for 1 minute
ArrayList<String> keyStrokeList = nativeMethods.getKeyStrokeList();
int result = copy.copyToLogFile(keyStrokeList);
System.out.println(result);
} catch(Exception exc) {
exc.printStackTrace();
}
}
我将描述一种情况:
Foo 线程已完成复制最后一分钟输入的所有数据,并且自睡眠以来已经过了30秒。这个线程没有意识到当几个键处于睡眠状态时被轻敲的情况,当按下System.exit(0)
时,它永远无法将键击复制到日志文件中。
有什么方法可以打断这个线程,即唤醒它并要求它将数据复制到日志文件。
请讨论我应该如何解决这个问题。
问题中的情况:
loop started
thread is sleeping and will sleep for 1 minute
after a minute,it gets the keys tapped in the last 1 minute and copies all that
to a file
Thread sleeps again..and will sleep for 1 minute before it copies the keystrokes
It has been about 30 seconds and thread will sleep for 30 seconds more before it starts
copying the key strokes
suddenly the user presses exit button in the application
The user wants that key strokes be recorded till the second he presses exit
I cannot do System.exit(0) before checking the thread is asleep or not
How do I do this. Should I awake it or make a different call to the list and get the
key strokes because they are being recorded ? And how shall I awake it ?
答案 0 :(得分:1)
你在那里... ...
while(isStarted) {
try {
Thread.sleep(60000); // sleep for 1 minute
} catch(InterruptedException exc) {
exc.printStackTrace();
}
ArrayList<String> keyStrokeList = nativeMethods.getKeyStrokeList();
int result = copy.copyToLogFile(keyStrokeList);
System.out.println(result);
}
您需要提供一种终止循环的方法......
public void dispose() {
isStarted = false;
interrupt();
try {
join();
} catch(InterruptedException exc) {
exc.printStackTrace();
}
}
您还应该知道,在所有非守护程序线程完成(正常关闭)之前,JVM不会退出。这意味着您可以调用System.exit(0)
,并且在记录器线程终止之前JVM不会终止。
你可以使用它,但附加一个shut down hook,它有能力在记录器线程上调用dispose
方法......只是一个想法
答案 1 :(得分:0)
您应该在2个线程之间使用共享对象来实现等待/通知模式而不是Thread.sleep(..)方法。
在您的情况下,有2个主题:
因此,每当您创建Thread1的实例时,您都可以将Java Object(new Object())传递给它。读者线程可以使用object.wait(60 * 1000)进入睡眠状态;因此,如果在1分钟内未调用object.notify(),它将睡眠最多1分钟。如果在此持续时间内调用了object.notify(),则线程将立即恢复。
因此,每当用户想要退出应用程序时,您都可以调用object.notify();这将恢复读者线程。
如果由于英语不好而无法向您解释解决方案,请告诉我。我将为您提供代码示例。
答案 2 :(得分:0)
这是一个相当简单的测试用例,展示了一种方法:
public class InterruptTest
{
@Test
public void test() throws InterruptedException
{
//Create the logging thread and start it
LogRunnable runnable = new LogRunnable();
Thread t = new Thread(runnable);
t.start();
//Wait some time
Thread.sleep(3500);
System.out.println("User has pressed exit, starting shutdown");
//Tell the runnable to shut down
runnable.halt();
//Interrupt the thread to wake it up
t.interrupt();
//Wait until thread terminates
t.join();
System.out.println("Exiting");
}
private static class LogRunnable implements Runnable
{
private static final int SLEEPMS = 2000;
private boolean isStarted = true;
private int runCount = 1;
public void halt()
{
this.isStarted = false;
}
public void run()
{
while(isStarted)
{
try
{
Thread.sleep(SLEEPMS);
}
catch(InterruptedException e)
{
System.out.println("Interrupted");
}
catch(Exception exc)
{
exc.printStackTrace();
}
//Do work
System.out.println("Work done " + runCount++);
}
}
}
}
输出:
Work done 1
User has pressed exit, starting shutdown
Interrupted
Work done 2
Exiting
InterruptedException
唤醒,在捕获和终止后完成代码join()
调用返回并终止