我正在处理一个应用程序,需要能够暂停主线程中间处理。我的想法是有三个线程:main,一个线程监听输入(STOP或GO命令)然后另一个线程导致main停止:
public static boolean stopped = false;
public static void main (String[] args){
Thread main = Thread.currentThread();
Runnable t1 = new Runnable() {
public void run() {
while(true){
Scanner s = new Scanner(System.in);
// wait for command
String in = s.nextLine();
if(in.equals("STOP")){
synchronized(main){
stopped = true;
//create new thread to make main wait
Runnable t2 = new Runnable() {
public void run(){
synchronized(main){
while(stopped){
main.wait();
}
}
}
};
Thread th2 = new Thread(t2);
th2.start();
}
}
if (in.equals("GO")){
synchronized(main){
stopped = false;
main.notifyAll();
}
}
}
}
};
Thread th1 = new Thread(t1);
th1.start();
while(true){
synchronized(main){
// Do lots of stuff that needs to pause when user enters STOP
System.out.println("Main is running");
Thread.sleep(5000);
}
}
}
}
即使在给出STOP命令之后,当前main仍继续循环。有没有办法锁定main直到另一个线程释放它而不必在main中执行wait()
?
答案 0 :(得分:3)
您不希望按照您的方式构建它。你不希望线程在任意点停止;在尝试恢复它时可能会导致问题。相反,给线程明确停止点。
例如,您可以创建一个工作线程,让程序的主线程管理命令并将指令委托给您的工作人员。 process
方法是增量工作量,例如读取大文件的一行。例如,让这成为你的工人任务:
public abstract class Worker implements Runnable {
private final Object lock = new Object();
private final AtomicBoolean shouldWait = new AtomicBoolean();
protected abstract boolean processingIsComplete();
protected abstract void process();
protected abstract void cleanUpResources();
public Object getLock() {
return lock;
}
public void disable() {
shouldWait.set(false);
}
public void enable() {
shouldWait.set(true);
}
@Override
public void run() {
try {
while(!processingIsComplete()) {
while(!shouldWait.get()) {
synchronized(lock);
lock.wait();
}
}
process();
}
} catch(InterruptedException e) {
System.out.println("Worker thread stopped");
} finally {
cleanUpResources();
}
}
}
然后,修改/子类worker以实际执行处理工作。然后,在您的主课程中,您可以根据需要打开和关闭您的工作人员。这只是一个框架,显然你可以将行为重构为多个方法,添加其他控件,如读取工作线程的状态等等:
public static void main (String[] args) throws Exception {
Worker worker = new WorkerImpl(/* whatever args are needed */);
Thread workerThread = new Thread(worker);
System.out.println("Starting process...");
worker.start();
Scanner sc = new Scanner(System.in);
while(true) {
System.out.printn("Please enter command: ");
String command = sc.nextLine();
if("END".equals(command)) {
System.out.println("Terminating program... ");
workerThread.interrupt();
break;
} else if ("GO".equals(command)) {
synchronized(worker.getLock()) {
System.out.println("Continuing worker thread... ");
worker.enable();
worker.getLock().notifyAll();
}
} else if ("STOP".equals(command)) {
synchronized(worker.getLock()) {
System.out.println("Stopping worker thread ");
worker.disable();
worker.getLock().notifyAll();
}
} else {
printCommandHelp();
}
}
};