如何从单独的线程中暂停主线程?

时间:2015-08-06 21:40:21

标签: java multithreading wait

我正在处理一个应用程序,需要能够暂停主线程中间处理。我的想法是有三个线程: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()

1 个答案:

答案 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();
    }
  }
};

进一步阅读:How to use wait and notify in Java?