【问题标题】:Java - Pausing a thread pool when it is executing with a JButtonJava - 使用 JButton 执行时暂停线程池
【发布时间】:2015-10-21 00:23:50
【问题描述】:

我的事件有一个暂停机制(可运行),但我不确定在需要调用它时如何使用/调用它。

在我的课堂上,我有一个 run 方法,它将一个充满事件的数组列表提交给一个执行程序。 (参见 GreenhouseControls 上的 run())。提交事件时,Thread.sleep(eventTime);被调用,然后事件内部的 action() 被调用。

我的程序要求需要一种机制,通过一个方法(单击时将由一个方法调用)暂停所有线程,该方法稍后可以通过另一个按钮恢复。

有人知道如何实现这个机制吗?

这里是文件:

GreenhouseControls.java

package control;
/**
 *  In this exercise we take a different design approach to GreenhouseControls 
 *  
 *  Compiled/Tested using Eclipse Version: Luna Release (4.4.0)
 *  TME4 Folder is located in C:\COMP 308\
 */
import java.io.*;
import java.util.regex.*;
import java.util.logging.*;
import java.util.*;
import java.util.concurrent.*;
import java.lang.reflect.*;

import tme4.*;


/**
 * GreenhouseControls consists of the Greenhouse's status and methods that
 * control what actions will be performed inside the Greenhouse.
 * @author Ray Masiclat
 *
 */
public class GreenhouseControls extends Controller implements Serializable{
    /**
     * status is a Set of StatusPair objects which contains information about the
     * GreenhouseControls' status. The Default States are initialized in the default constructor.
     */
    private Set<StatusPair> status = new HashSet<StatusPair>();
    private static String file = "src/error.log";


    /**
     * Default Constructor -    initializes each state of the Greenhouse
     * 
     */
    public GreenhouseControls(){
        status.add(new StatusPair<String, Boolean>("light", false));
        status.add(new StatusPair<String, Boolean>("water", false));
        status.add(new StatusPair<String, Boolean>("fans", false));
        status.add(new StatusPair<String, Boolean>("windowok", true));
        status.add(new StatusPair<String, Boolean>("poweron", true));
        status.add(new StatusPair<String, String>("thermostat", "Day"));
        status.add(new StatusPair<String, Integer>("errorcode", 0));
        status = Collections.synchronizedSet(status);
    }

    /**
     * Prints out in the console how to use the program.
     */
  public static void printUsage() {
    System.out.println("Correct format: ");
    System.out.println("  java GreenhouseControls -f <filename>, or");
    System.out.println("  java GreenhouseControls -d dump.out");
  }
  /**
   * Takes in an errorcode and returns the appropriate Fix that will fix the
   * error that occured in the past.
   * @param errorcode
   * @return fix
   */
  public Fixable getFixable(int errorcode){
      Fixable fix = null;
      switch(errorcode){
      case 1:
          fix = new FixWindow(this);
          break;
      case 2:
          fix = new PowerOn(this);
          break;
      default:
          System.out.println("No Error");
          break;
      }
      return fix;
  }

  /**
   * shutdown - method creates a Logger that creates an error log which consists of information about the
   * reason of why the program was shut down. After logging the error information, it serializes
   * the current state of the program in order for it to be fixed/restored in the future.
   * @throws IOException
   */
  public void shutdown() throws IOException{
      System.err.println("System Shutting Down");
      Logger logger = Logger.getLogger("ControllerException");
      FileHandler fh;
      try {
          fh = new FileHandler("src/error.log");
          logger.addHandler(fh);
          SimpleFormatter formatter = new SimpleFormatter();
          fh.setFormatter(formatter);
      } catch (SecurityException e) {
          e.printStackTrace();
      } catch (IOException e) {
          e.printStackTrace();
      }
      //Check for errorcode using getError method.
      int checkError = this.getError();
      if(checkError == 1){
          logger.info("Window Malfunction");
      } else if (checkError == 2){
          logger.info("Power Outage");
      } else {
          logger.info("No Error");
      }
     /**
      * Serialize the current state and output it onto the src/ directory as dump.out
      */
      ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("src/dump.out"));
      out.writeObject(this);
      out.writeObject(getEventList());
      out.close();
      System.exit(0);
  }

  /**
   * getStatus - returns the status Set which consists of information about the current state of the program.
   * @return status
   */
  public Set<StatusPair> getStatus(){
      return status;
  }

  /**
   * getError - Assigns an integer which will be used when logging the error.
   * The errorNum is retrieved using the status Set
   * @return errorNum
   */
  public int getError(){
      int errorNum = 0;
      //Iterate through the status Set
      for(StatusPair sp : status){
          //Check for the name "errorcode" and initializes errorNum from its status
          if(sp.getName().equals("errorcode")){
              errorNum = (int) sp.getStatus();
          }
      }
      return errorNum;
  }

  /**
   * getEventList - returns a List of Events in the program.
   * @return eventList
   */
  public List<Event> getEventList(){
      return eventList;
  }

  /**
   * Create a method in GreenhouseControls called setVariable to 
   * handle updating to this collection. Use the synchronization feature 
   * in java to ensure that two Event classes are not trying to add to 
   * the structure at the same time.
   * s - represents the name of the status
   * o - represents the status it is going to be replaced with
   * @param s
   * @param o
   */
  public void setVariable(String s, Object o){
      for(StatusPair sp : getStatus()){
          if(sp.getName().equals(s))
          {
              sp.setStatus(o);
          }
      }
  }

  /**
   * addStatus - Adds a new status in the status Set and it is used
   * if the program cannot find a name in the status Set.
   * @param name
   * @param status
   */
  public void addStatus(String name, Object status){
      getStatus().add(new StatusPair<String, Object>(name,status));
  }

  /**
   * run -  creates a thread array which will be used to run Events from
   *        the text file. Then a for loop is created to fill up the thread
   *        array with Events on each index. Then the thread is started once
   *        an index is initialized. After an event is added in to the thread
   *        array it is removed from the events list.
   */
public void run(){
    ExecutorService exec = Executors.newCachedThreadPool();
    if(eventList.size() == 1){
        exec.submit(eventList.get(0));
        eventList.remove(eventList.get(0));
    } else {
        for(Event e : eventList){
            exec.submit(e);
        }
    }
    exec.shutdown();

    /*while(eventList.size() > 0){
        for(int i = 0; i < eventList.size(); i++){
            exec.submit(eventList.get(i));
        }
    }*/
      /*Thread[] threads = new Thread[eventList.size()];
      while(eventList.size() > 0)
      for(int i = 0; i < eventList.size(); i++){
          threads[i] = new Thread(eventList.get(i));
          threads[i].start();
          eventList.remove(i);
      }*/
  }
} ///:~

Event.java

/**
 *  Make Event implements Runnable so that each type of event provides 
 *  its own timing. Each event file should be a class of its own. Change 
 *  the rest of the design to simplify this model.
 *  
 *  Assignment: TME4
 *  @author Ray Masiclat
 *  @studentid 3231308
 *  @date July 27, 2015
 *  
 *  
 *  Compiled/Tested using Eclipse Version: Luna Release (4.4.0)
 *  TME4 Folder is located in C:\COMP 308\
 */
package tme4;

import java.io.*;
import java.util.logging.FileHandler;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;

import gui.*;
import control.*;
/**
 * Event class that implements Runnable and Serializable
 * @author Ray Masiclat
 *
 */
public abstract class Event implements Runnable, Serializable{
    /**
     * eventTime - represents time it takes for the program to wait and then
     *              call its action method.
     */
    protected long eventTime;
    protected GreenhouseControls gcontrol;
    protected boolean suspended = false;
    /**
     * Event class constructor which is used to initialize the Event's eventTime and
     * GreenhouseControls object which is used for the Event to have access to its status
     * variables.
     * @param gc
     * @param eventTime
     */
    public Event(GreenhouseControls gc,long eventTime){
        this.eventTime = eventTime;
        this.gcontrol = gc;
    }

    /**
     * getTime - returns the event's eventTime initialized from the constructor.
     * @return eventTime
     */
    public long getTime(){
        return eventTime;
    }

    /**
     * setTime - sets the eventTime
     */
    public void setTime(long eventTime){
        this.eventTime = eventTime;
    }
    /**
     * run -    Event class' run method is called when the Event is added in to the Thread
     *          and then "started". This method puts the Thread to sleep for however long the
     *          eventTime is. Afterwards, once it is done, it tries to run the Event's action
     *          method. If the action method throws an error, it is caught by the try-catch
     *          block which calls the GreenhouseControls object's shutdown which outputs an error.log
     *          file and serializes the current state of the GreenhouseControls object to a dump.out file.
     */
    public void run(){

        try {
            synchronized(this){
                while(suspended){
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
            Thread.sleep(eventTime);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        try {
            this.action();
        } catch (ControllerException e) {
            //Use shutdown to create error log
            try {
                gcontrol.shutdown();
            } catch (IOException e1) {
                // TODO Auto-generated catch block
                e1.printStackTrace();
            }
            e.printStackTrace();
        }
    }

    public void suspend(){
        suspended = true;
    }

    public synchronized void resume(){
        suspended = false;
        notify();
    }

    /**
     * abstract method used to call an Event's action method in the run method.
     * @throws ControllerException
     */
    public abstract void action() throws ControllerException;
} ///:~

(Pastebin: GreenhouseControls.javaEvent.java)

【问题讨论】:

  • 如果您在问题中发布相关代码会更好,发布完整的代码文件有利于上下文,但当用户必须查看超过 200 行的文件时,很难获得帮助。
  • @yvesmancera 相关代码在我相信的问题中,我认为更好地了解整个班级会更容易理解。请就我的问题提出任何不清楚的问题。

标签: java multithreading concurrency threadpool executor


【解决方案1】:

类似这样的:

布尔停止 = 假;

您可以像这样使用暂停/停止对象

public class Stopping {

  public synchronized void checkStop() {
    if (stopped) {
      wait(); // wait until stop has been cleared
    }
  }

  public synchronized void setStop(boolean val) {
    stop = val;
    if (val) {
      notifyAll();
    }
  }
}

创建其中一个并与所有线程共享,确保经常调用 checkStop()。或者,您可以将此类中的方法设为静态,然后您的线程就不需要对象引用——它们只需调用 Stopping.checkStop();

【讨论】:

  • 我应该把它作为一个 Inner 类添加到我的 GreenhouseControls 中吗?
  • 我不这么认为,除非您使用静态选项。但是您的方式不一定是错误的;你只需要确保每个线程都使用相同的对象/锁
  • 伙计,我认为您的解决方案是有道理的,但我无法弄清楚我将如何实施它!我会继续努力的!非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-07-24
  • 1970-01-01
  • 2014-08-27
  • 2017-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多