我有一个Java程序,我用它来显示有关通过网络发送给用户的流量的信息。目前,用户必须单击“开始”按钮才能开始接收和查看该信息,然后单击“停止”按钮以停止接收该信息。
但是,正如我的代码目前一样,它只会在用户第一次点击“开始”按钮时工作......一旦他们点击“停止”,如果他们再次尝试点击“开始”,控制台显示错误:
线程“AWT-EventQueue-0”中的异常java.util.concurrent.RejectedExecutionException:任务...从java.util.concurrent.ThreadPoolExecutor中拒绝...已终止,池大小= 0,活动线程= 0,已完成tasks = 1]
显示网络流量信息的代码位于while循环中,该循环只是不断循环。在while循环结束时,我有以下代码,我用它来退出循环/停止捕获:
Boolean queryStopCapture = stopCapture;
if(queryStopCapture == true){
System.out.println("Break clause in 'queryStopCapture' if statement has been called. ");
break;
queryStopCapture
的值设置为stopCapture
的值,默认为false
,但true
时更改为ActionListener
听到点击GUI中的“停止”按钮。
任何人都可以向我解释这个Exception的含义,为什么我在尝试重新启动捕获时会得到它,以及在尝试重新启动捕获时我如何“适应”它?
围绕使用try / catch块点击“开始捕获”按钮的代码是否有效?
编辑30/04/2014 @ 11:50
这是我用来“接收”通过网络发送的流量的完整课程:
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 */
这是我的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);
}
});
}
}
答案 0 :(得分:0)
我假设您使用的是线程或类似的东西?你不能再次开始一个线程。您应该使用同步机制来暂停/恢复线程,或者使用可以重新启动的东西(比如runnable与执行器服务的组合)。
答案 1 :(得分:0)
停止服务时不要使用游泳池关闭。
因为一旦关闭它将完成队列中的所有任务 并且不会接受队列中的任何其他任务。
解决方案:删除pool.shutdown();来自您代码中的以下方法。
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();
}
});
将标志设置为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");
}
}
});