简体   繁体   English

Java-停止程序后再次启动程序,而不关闭程序

[英]Java- starting a program again after stopping it, without closing it down

I have a Java program which I am using to display information about the traffic that's being sent over a network to the user. 我有一个Java程序,用于显示有关通过网络发送给用户的流量的信息。 Currently, the user has to click a 'start' button to begin receiving and viewing that information, and then clicks a 'stop' button to stop receiving that information. 当前,用户必须单击“开始”按钮以开始接收和查看该信息,然后单击“停止”按钮以停止接收该信息。

However, as my code currently stands, it will only work the first time that the user click the 'start' button... Once they have clicked 'stop', if they try to click 'start' again, a console error is displayed that says: 但是,按照我当前的代码,它仅在用户第一次单击“开始”按钮时才起作用...单击“停止”后,如果再次尝试单击“开始”,则会显示控制台错误说的是:

Exception in thread "AWT-EventQueue-0" java.util.concurrent.RejectedExecutionException: Task ... rejected from java.util.concurrent.ThreadPoolExecutor... Terminated, pool size = 0, active threads = 0, completed tasks = 1] 线程“ AWT-EventQueue-0”中的异常java.util.concurrent.RejectedExecutionException:任务...被java.util.concurrent.ThreadPoolExecutor拒绝...已终止,池大小= 0,活动线程= 0,已完成的任务= 1 ]

The code that is displaying the network traffic information is in a while loop, which just loops continually. 显示网络流量信息的代码处于while循环中,该循环只是不断循环。 At the end of the while loop, I have the following code, which I am using to exit the loop/ stop the capture: 在while循环的结尾,我有以下代码,我正在使用这些代码退出循环/停止捕获:

Boolean queryStopCapture = stopCapture;
if(queryStopCapture == true){
    System.out.println("Break clause in 'queryStopCapture' if statement has been called. ");
    break;

The value of queryStopCapture is set equal to the value of stopCapture , which is false by default, but is changed to true when the ActionListener hears a click on the 'Stop' button in the GUI. queryStopCapture被设定为等于值stopCapture ,这是false默认,但更改为trueActionListener听到GUI中的“停止”按钮的点击。

Can anyone explain to me what this Exception means, why I'm getting it when trying to restart the capture, and how I can 'accommodate' it when trying to restart the capture? 谁能向我解释此异常的含义,为什么在尝试重新启动捕获时会收到此异常,以及在尝试重新启动捕获时如何“容纳”该异常?

Would surrounding the code that's listening for a click on the 'start Capture' button with a try/catch block work? 在尝试/捕获块的周围是否包含正在监听单击“开始捕获”按钮的代码?

Edit 30/04/2014 @ 11:50 编辑30/04/2014 @ 11:50

This is the full class that I am using to 'receive' the traffic that's being sent over the network: 这是我用来“接收”通过网络发送的流量的完整类:

import java.io.Console;
import java.net.*;
import java.util.ArrayList;
import java.applet.*;
import java.awt.*;

import edu.nps.moves.disutil.*;
import edu.nps.moves.dis.*;

/*Receives PDUs from the network in IEEE format. */

public class EspduReceiver {

/*Max size of a PDU in binary format that can be received. Outdated- PDUs can be larger- but this is a reasonable starting point */
public static final int MAX_PDU_SIZE = 8192;

/*Retrieve PDU data for use by class methods */
static MulticastSocket socket;
static DatagramPacket packet;
static InetAddress address;
static PduFactory pduFactory = new PduFactory();

/*Every PDU received by the application will be dynamically added to this ArrayList- so I should be able to access each PDU
 * from anywhere, using each element of the ArrayList. */
public static ArrayList<Pdu> espdu = new ArrayList<Pdu>(); /*Currently, this ArrayList is storing the actual DIS messages- which aren't really 
                                                            human readable */
public static ArrayList<Integer> entitySite = new ArrayList<Integer>();
public static ArrayList<Integer> entityApplication = new ArrayList<Integer>();
public static ArrayList<Integer> entity = new ArrayList<Integer>();

//public static Pdu pdu = pduFactory.createPdu(packet.getData());
//public static EntityID eid = ((EntityStatePdu)pdu).getEntityID();
//public static Vector3Double position = ((EntityStatePdu)pdu).getEntityLocation();

public static void receivePdu(){

    //while(true){

        try{
            /*Specify the socket to receive the data */
            socket = new MulticastSocket(EspduSender.PORT);
            address = InetAddress.getByName(EspduSender.DEFAULT_MULTICAST_GROUP);
            socket.joinGroup(address); 

            /*Loop infinitely, receiving datagrams */
            while(true){
                byte buffer[] = new byte[MAX_PDU_SIZE];
                packet = new DatagramPacket(buffer, buffer.length);

                socket.receive(packet);

                Pdu pdu = pduFactory.createPdu(packet.getData()); /*Moved this line to the top of the class to declare as global variable (29/04/2014) */

                if(pdu != null){
                    System.out.print("Got PDU of type: " + pdu.getClass().getName());
                    if(pdu instanceof EntityStatePdu){
                        EntityID eid = ((EntityStatePdu)pdu).getEntityID(); /*Moved this line to the top of class to declare as global variable (29/04/2014) */
                        Vector3Double position = ((EntityStatePdu)pdu).getEntityLocation(); /*Moved this line to the top of class to declare as global variable (29/04/2014) */
                        System.out.println(" EID:[" + eid.getSite() + ", " + eid.getApplication() + ", " + eid.getEntity() + "] ");
                        System.out.println("Location in DIS coordinates: [" + position.getX() + ", " + position.getY() + ", " + position.getZ() + "] ");
                        /*Add PDU to ArrayList of PDUs */
                        espdu.add(pdu);
        /*              System.out.println(" PDU added to arrayList. "); 
                        System.out.println(espdu); /*This is printing out the actual DIS messages (i.e. edu.nps.moves.dis.EntityState...),
                        maybe try adding the 'eid.getSite()', etc to an ArrayList instead. Use Associative arrays/ map/ hashmap */

                        entitySite.add(eid.getSite());
                        System.out.println("Entity Site added to ArrayList. ");
                        entityApplication.add(eid.getApplication());
                        System.out.println("Entity Application added to ArrayLIst. ");
                        entity.add(eid.getEntity());
                        System.out.println("Entity ID added to ArrayList");

                        /*Check that everything is actually in the ArrayLists 
                        for(int i : entity){ /*Substituted 'entity' with 'entitySite' and 'entityApplication'- values are all printed correctly. 
                        System.out.println(i);
                        } */

                        /*Now append each PDU to the text area */
                        Gui.displayOutput.append("\n");
                        Gui.displayOutput.append("EID: [" + eid.getSite() + ", " + eid.getApplication() + ", " + eid.getEntity() + "]. ");
                        Gui.displayOutput.append("Location in DIS coordinates: [" + position.getX() + ", " + position.getY() + ", " + position.getZ() + "] ");

                    } else if(!(pdu instanceof EntityStatePdu)){
                        System.out.println("There are no PDUs currently being received.");
                    }
                    System.out.println();
                }
                Thread.sleep(1000);
                /*Try adding a boolean to allow me to stop the capture by clicking 'stop' button- Look on stackoverflow */
                boolean queryStopCapture =  stopCapture;
                if(queryStopCapture ==  true){
                    System.out.println("Break clause in 'queryStopCapture' if statement has been called. ");
                    break;
                } 
            } /*end while */
        } /*end try */
        catch(Exception e){
            System.out.println(e);
            e.printStackTrace();
            System.out.println("This is where the error is being generated");
            /*09/04/2014 @ 17:100
             * If this exception gets called, presumably it either means that pdu is not an instance of EntityStatePdu, or
             * that pdu does not actually hold a packet.  */
        }
        /*Try adding a boolean to allow me to stop the capture by clicking 'stop' button- Look on stackoverflow */
    /*  boolean queryStopCapture =  stopCapture;
        if(queryStopCapture ==  true){
            break;
        } */
    //}
}

public static boolean stopCapture = false;

public static void main(String args[]){

    receivePdu();
/*  MulticastSocket socket;
    DatagramPacket packet;
    InetAddress address;
    PduFactory pduFactory = new PduFactory();

    try{
        /*Specify the socket to receive the data 
        socket = new MulticastSocket(EspduSender.PORT);
        address = InetAddress.getByName(EspduSender.DEFAULT_MULTICAST_GROUP);
        socket.joinGroup(address); 

        /*Loop infinitely, receiving datagrams 
        while(true){
            byte buffer[] = new byte[MAX_PDU_SIZE];
            packet = new DatagramPacket(buffer, buffer.length);

            socket.receive(packet);

            Pdu pdu = pduFactory.createPdu(packet.getData()); /*    Commented on 15/04/2014 @ 09:15 

            if(pdu != null){
                System.out.print("Got PDU of type: " + pdu.getClass().getName());
                if(pdu instanceof EntityStatePdu){
                    EntityID eid = ((EntityStatePdu)pdu).getEntityID();
                    Vector3Double position = ((EntityStatePdu)pdu).getEntityLocation();
                    System.out.print(" EID:[" + eid.getSite() + ", " + eid.getApplication() + ", " + eid.getEntity() + "] ");
                    System.out.print(" Location in DIS coordinates: [" + position.getX() + ", " + position.getY() + ", " + position.getZ() + "]");
                } else if(!(pdu instanceof EntityStatePdu)){
                    System.out.println("There are no PDUs currently being received.");
                }
                System.out.println();
            }
        } /*end while 
    } /*end try 
    catch(Exception e){
        System.out.println(e);
        e.printStackTrace();
        System.out.println("This is where the error is being generated");
        /*09/04/2014 @ 17:100
         * If this exception gets called, presumably it either means that pdu is not an instance of EntityStatePdu, or
         * that pdu does not actually hold a packet.  
    } */
} /*end main */

/*Create an 'Inner Class' (use as a C struct) to hold all of the variables pertaining to each PDU- each instance of the class
 * will hold a separate PDU. 
 * Create a method in Gui.java that will retrieve each instance of the inner class, and display the values on screen.*/

public class PDU{

    public String entityID;
    public double xLocation;
    public double yLocation;
    public double zLocation;
}



} /*end class */

and this is the code for my Gui.java class: 这是我的Gui.java类的代码:

import java.applet.*;
import java.awt.*;

import javax.swing.*;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Gui extends JFrame{

public static String text = "";
public static int rows = 20;
public static int columns = 5;
public static JTextArea displayOutput = new JTextArea(text, rows, columns);

/*Create a JComboBox to display filter options, and JTextField to allow user to enter filter criteria */
public static String[] filterOptions = {"", "Site", "Application", "ID"};
public static JComboBox<String> filter1 = new JComboBox<String>(filterOptions); /*Adding the '<String>' parameters to JComboBox got rid of the warnings 29/04/2014 */
public static JTextField filter1Text = new JTextField();
public static JComboBox filter2 = new JComboBox(filterOptions);
public static JTextField filter2Text = new JTextField();
public static JComboBox filter3 = new JComboBox(filterOptions);
public static JTextField filter3Text = new JTextField();

public Gui(){
    setTitle("DIS Filter");
    setSize(1000, 500);
    setLocation (10, 10);
    setDefaultCloseOperation(EXIT_ON_CLOSE);

    initGui();
}

/*public quitButton(){
    initGui();
} */

private void initGui(){
    //JFrame frame = new JFrame();
    JPanel panel = new JPanel();

    this.getContentPane().add(panel);
    this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    this.setTitle("DIS Filter");
    this.setSize(1200, 600);

    panel.setLayout(null);
    /*Add a JTextArea to display the output DIS information */
    //JTextArea displayOutput = new JTextArea(text, rows, columns);
    displayOutput.setBounds(10, 10, 700, 500);
    panel.add(displayOutput);
    displayOutput.setEditable(false);
    //displayOutput.setEditable(false);
    add(panel);
    //displayOutput.append("hello");


    //String data = EspduReceiver.espdu;
//  EspduReceiver.receivePdu(); /*The code underneath here will never be reached unless I specify how long to perform this method call for- */
                                /*Since the receivePdu() method has no 'end' condition- it keeps looping continually until told to stop */
                                /*Try using a timer to specify how long it should be called for */
    long start = System.currentTimeMillis();
    long end = start + 60*1000; /* 60 seconds * 1000 ms/sec */
/*  while (System.currentTimeMillis() < end){

        int n = EspduReceiver.entitySite.size(); /*This is what to use, but set n to 10 for testing purposes. 
        //int n = 10;
        System.out.print(n);
        for (int i = 0; i < n; i++){
//          EspduReceiver.receivePdu();
            System.out.print("Entered 'for' loop. ");
            System.out.println(EspduReceiver.entitySite.get(i));
            System.out.println(EspduReceiver.entityApplication.get(i));
            System.out.println(EspduReceiver.entity.get(i));
            displayOutput.append(EspduReceiver.entitySite.get(i).toString());
            displayOutput.append(EspduReceiver.entityApplication.get(i).toString());
            displayOutput.append(EspduReceiver.entity.get(i).toString());
        }       
    } */ /*Maybe need to move this while loop into another class/ add the code to the method that I will call to display output */



    /*Create an ExecutorService and then call shutdown in my ActionListener for stop */
    final ExecutorService pool = Executors.newSingleThreadExecutor();

    /*Create 'Quit' button and add it to the panel */
    JButton quitButton = new JButton("Quit");
    panel.add(quitButton);
    quitButton.setBounds(1080, 500, 80, 30); /*Set the location of the button in the window, and its size */

    quitButton.addActionListener(new ActionListener(){
        @Override
        public void actionPerformed(ActionEvent e){
            System.exit(0);
            pool.shutdown();
        }
    });

    //panel.add(quitButton);
    //setTitle("Quit");
    //setSize(60,30); /*This line was overwriting the previously set values for the size of the window */
    setLocationRelativeTo(null);
    panel.repaint();
    setDefaultCloseOperation(EXIT_ON_CLOSE);    


    /*Create 'StartCapture' button and add it to the panel */
    JButton startCaptureButton = new JButton("Start");
    panel.add(startCaptureButton);
    startCaptureButton.setBounds(1080, 350, 80, 30);

    startCaptureButton.addActionListener(new ActionListener(){
        @Override
        public void actionPerformed(ActionEvent e){
            /*Try adding ExecutorService code here */
            pool.execute(new Runnable(){
                public void run(){
                    /*For some reason, the call to EspduReceiver.receivePdu(); doesn't work if the capture has already been stopped once.
                     * Tried surrounding it with a try/catch block, but this didn't make a difference */
                    try{
                        EspduReceiver.receivePdu();
                    } catch(Exception e){
                        System.out.println("Cannot start capture again after stopping");
                    }
                }
            });
            /*Add method call to receivePdu(); here */
            //EspduReceiver.receivePdu();
        }
    });


    /*Create 'StopCapture' button and add it to the panel */
    JButton stopCaptureButton = new JButton("Stop");
    panel.add(stopCaptureButton);
    stopCaptureButton.setBounds(1080, 400, 80, 30);

    stopCaptureButton.addActionListener(new ActionListener(){
        @Override
        public void actionPerformed(ActionEvent e){
            EspduReceiver.stopCapture = true;
            pool.shutdown();
        }
    });

    /*Add the filters to the window */
    panel.add(filter1);
    filter1.setBounds(720, 50, 100, 30);
    panel.add(filter1Text);
    filter1Text.setBounds(850, 50, 200, 30);

    panel.add(filter2);
    filter2.setBounds(720, 90, 100, 30);
    panel.add(filter2Text);
    filter2Text.setBounds(850, 90, 200, 30);

    panel.add(filter3);
    filter3.setBounds(720, 130, 100, 30);
    panel.add(filter3Text);
    filter3Text.setBounds(850, 130, 200, 30);


    /*Add buttons that will call 'retrieve' functions from Filter.java, and display only the entities that match the filtered
     *  values in the GUI. */

    /*Get entities with matching site */
    JButton getSiteEntitiesButton = new JButton("Get Site entities");
    panel.add (getSiteEntitiesButton);
    getSiteEntitiesButton.setBounds(900, 400, 80, 30);

    getSiteEntitiesButton.addActionListener(new ActionListener(){
        @Override
        public void actionPerformed(ActionEvent e){
            /*Need to check if there are any PDUs stored in 'entity' arrays first- if there aren't, then add a call to receivePdu() at
             *  the start of this method; if there are, then get the value entered into the text box, and search through the array for 
             *  a matching value.  */
            try{
            if(EspduReceiver.entitySite.get(0) == null){
                EspduReceiver.receivePdu();
                Filter.retrieveFilteredSite();
            } else {
            /*Need to add code to retrieve value of 'filter1Text */
            Filter.retrieveFilteredSite();
            }

            }catch(Exception ex){
                System.out.println("No PDUs have yet been received. You must receive at least one PDU before you can search for a matching site entity. ");
            }
        }
    });

}

public static void main(String[] args){ /* I probably don't need a main method here- I have one in EspduReceiver.java */
    SwingUtilities.invokeLater(new Runnable(){
        @Override
        public void run(){
            Gui gui = new Gui();
            gui.setVisible(true);
        }
    });
}




}

I assume you are using a thread or something similar? 我假设您正在使用线程或类似的东西? You cannot just start a thread again. 您不能只是再次启动线程。 You should either use a synchronization mechanism to pause/resume the thread or use something you can start again (like a runnable in combination with an executor service). 您应该使用同步机制来暂停/恢复线程,或者使用可以再次启动的东西(例如与可执行程序服务结合使用的runnable)。

dont use pool shutdown during stop of your service. 服务停止期间不要使用池关闭功能。

because once you shutdown it will finish all the tasks in the queue and will not accept any more tasks from the queue. 因为一旦关闭,它将完成队列中的所有任务,并且不再接受队列中的其他任务。

solution : remove pool.shutdown(); 解决方案:删除pool.shutdown(); from the below method in your code. 从您的代码中的以下方法。

 JButton stopCaptureButton = new JButton("Stop");
    panel.add(stopCaptureButton);
    stopCaptureButton.setBounds(1080, 400, 80, 30);

    stopCaptureButton.addActionListener(new ActionListener(){
        @Override
        public void actionPerformed(ActionEvent e){
            EspduReceiver.stopCapture = true;
            pool.shutdown();
        }
    });

set flag as false for start action 将标志设置为false以进行启动操作

startCaptureButton.addActionListener(new ActionListener(){
        @Override
        public void actionPerformed(ActionEvent e){
            /*Try adding ExecutorService code here */
EspduReceiver.stopCapture = false;
            pool.execute(new Runnable(){
                public void run(){
                    /*For some reason, the call to EspduReceiver.receivePdu(); doesn't work if the capture has already been stopped once.
                     * Tried surrounding it with a try/catch block, but this didn't make a difference */
                    try{
                        EspduReceiver.receivePdu();
                    } catch(Exception e){
                        System.out.println("Cannot start capture again after stopping");
                    }
                }
            });

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM