如果线程启动Executor,则无法从Future <?>和SwingWorker获取ArrayIndexOutOfBoundsException

我使用Executor来玩SwingWorker的multithreading,而且我从那里错误的发现了Vector中的错误元素,看起来像这段代码很可能忽略了Vector中不存在的元素

我的问题 – >如何/有可能以某种方式捕捉这个exception

简单的输出

run: Thread Status with Name :StartShedule, SwingWorker Status is STARTED Thread Status with Name :StartShedule, SwingWorker Status is DONE Thread Status with Name :StartShedule, SwingWorker Status is STARTED Thread Status with Name :StartShedule, SwingWorker Status is DONE Thread Status with Name :StartShedule, SwingWorker Status is STARTED Thread Status with Name :StartShedule, SwingWorker Status is DONE BUILD SUCCESSFUL (total time: 11 seconds) 

通过取消注释

 //changeTableValues1(); // un-comment for get ArrayIndexOutOfBoundsException 

一切正常,我得到ArrayIndexOutOfBoundsException和输出是

 run: Exception in thread "AWT-EventQueue-0" java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 2 at java.util.Vector.get(Vector.java:694) at KondorExport.Util.Help.Table.TableWithExecutor.changeTableValues1(TableWithExecutor.java:70) at KondorExport.Util.Help.Table.TableWithExecutor.access$100(TableWithExecutor.java:18) at KondorExport.Util.Help.Table.TableWithExecutor$2.actionPerformed(TableWithExecutor.java:61) at javax.swing.Timer.fireActionPerformed(Timer.java:271) at javax.swing.Timer$DoPostEvent.run(Timer.java:201) at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209) at java.awt.EventQueue.dispatchEvent(EventQueue.java:597) at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269) at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184) at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169) at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161) at java.awt.EventDispatchThread.run(EventDispatchThread.java:122) Thread Status with Name :StartShedule, SwingWorker Status is STARTED Thread Status with Name :StartShedule, SwingWorker Status is DONE BUILD SUCCESSFUL (total time: 10 seconds) 

来自代码

 import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.util.List; import java.util.Vector; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import javax.swing.*; import javax.swing.table.*; public class TableWithExecutor extends JFrame { private static final long serialVersionUID = 1L; private String[] columnNames = {"Narrative", "Description"}; private Object[][] data = {{"About", "About"}, {"Add", "Add"}}; private JTable table; private Executor executor = Executors.newCachedThreadPool(); private Timer timerRun; private int delay = 3000; private Vector<String> fwDeals; private Vector<String> fwDeals1; public TableWithExecutor() { DefaultTableModel model = new DefaultTableModel(data, columnNames); table = new JTable(model) { private static final long serialVersionUID = 1L; @Override public Class getColumnClass(int column) { return getValueAt(0, column).getClass(); } }; table.setPreferredScrollableViewportSize(table.getPreferredSize()); JScrollPane scrollPane = new JScrollPane(table); add(scrollPane, BorderLayout.CENTER); prepareStartShedule(); } private void prepareStartShedule() { timerRun = new javax.swing.Timer(delay, startCycle()); timerRun.setRepeats(true); timerRun.start(); } private Action startCycle() { return new AbstractAction("Start Shedule") { private static final long serialVersionUID = 1L; @Override public void actionPerformed(ActionEvent e) { executor.execute(new TableWithExecutor.MyTask("StartShedule")); //non on EDT //changeTableValues1(); // un-comment for get ArrayIndexOutOfBoundsException } }; } private void changeTableValues1() { fwDeals1 = new Vector<String>(); fwDeals1.add("First"); // ElementAt(0) fwDeals1.add("Second");// ElementAt(1) checkDealsInDb1(fwDeals1.get(1), fwDeals1.get(2)); } private void checkDealsInDb1(String Str, String Str1) { table.getModel().setValueAt(Str, 0, 1); table.getModel().setValueAt(Str1, 1, 1); } private void changeTableValues() { fwDeals = new Vector<String>(); fwDeals.add("First"); // ElementAt(0) fwDeals.add("Second");// ElementAt(1) checkDealsInDb(fwDeals.get(1), fwDeals.get(2)); } private void checkDealsInDb(String Str, String Str1) { table.getModel().setValueAt(Str, 0, 1); table.getModel().setValueAt(Str1, 1, 1); } public static void main(String[] args) { TableWithExecutor frame = new TableWithExecutor(); frame.setDefaultCloseOperation(EXIT_ON_CLOSE); frame.setLocation(150, 150); frame.pack(); frame.setVisible(true); } private class MyTask extends SwingWorker<Void, Integer> { private String str; private String namePr; MyTask(String str) { this.str = str; addPropertyChangeListener(new SwingWorkerCompletionWaiter(str, namePr)); } @Override protected Void doInBackground() throws Exception { if (str.equals("StartShedule")) { changeTableValues(); } return null; } @Override protected void process(List<Integer> progress) { } @Override protected void done() { if (str.equals("StartShedule")) { } } } private class SwingWorkerCompletionWaiter implements PropertyChangeListener { private String str; private String namePr; SwingWorkerCompletionWaiter(String str, String namePr) { this.str = str; this.namePr = namePr; } SwingWorkerCompletionWaiter(String namePr) { this.namePr = namePr; } @Override public void propertyChange(PropertyChangeEvent event) { if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.DONE == event.getNewValue()) { System.out.println("Thread Status with Name :" + str + ", SwingWorker Status is " + event.getNewValue()); } else if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.PENDING == event.getNewValue()) { System.out.println("Thread Status with Mame :" + str + ", SwingWorker Status is " + event.getNewValue()); } else if ("state".equals(event.getPropertyName()) && SwingWorker.StateValue.STARTED == event.getNewValue()) { System.out.println("Thread Status with Name :" + str + ", SwingWorker Status is " + event.getNewValue()); } else { System.out.println("SomeThing Wrong happends with Thread Status with Name :" + str); } } } } 

编辑:

添加从未来#重新抛出()done()方法(由@takteek优秀的build议)

 @Override protected void done() { if (str.equals("StartShedule")) { try { get(); //errLabel.setText(String.valueOf(get())); } catch (InterruptedException ie) { ie.printStackTrace(); } catch (ExecutionException ee) { ee.printStackTrace(); }catch (IllegalStateException is) { is.printStackTrace(); } } } 

但输出仍然是唯一的Got exception ,将很难从这BlackBox的任何例外

 run: Got exception Thread Status with Name :StartShedule, SwingWorker Status is STARTED Thread Status with Name :StartShedule, SwingWorker Status is DONE Got exception Thread Status with Name :StartShedule, SwingWorker Status is STARTED Thread Status with Name :StartShedule, SwingWorker Status is DONE Got exception Thread Status with Name :StartShedule, SwingWorker Status is STARTED Thread Status with Name :StartShedule, SwingWorker Status is DONE Got exception Thread Status with Name :StartShedule, SwingWorker Status is STARTED Thread Status with Name :StartShedule, SwingWorker Status is DONE BUILD SUCCESSFUL (total time: 13 seconds) 

我不确定它增加了多less,但我得到了预期Caused by使用下面显示的takteek的答案的变化Caused by 。 我从命令行运行它,以确保IDE不“帮助”。

 $ java -cp build / classes TableWithExecutor
 StartShedule:PENDING  - > STARTED
 java.util.concurrent.ExecutionException:java.lang.ArrayIndexOutOfBoundsException:数组索引超出范围:2
    在java.util.concurrent.FutureTask $ Sync.innerGet(FutureTask.java:222)
    在java.util.concurrent.FutureTask.get(FutureTask.java:83)
    在javax.swing.SwingWorker.get(SwingWorker.java:582)
    在TableWithExecutor $ MyTask.done(TableWithExecutor.java:103)
    在javax.swing.SwingWorker $ 5.run(SwingWorker.java:717)
    在javax.swing.SwingWorker $ DoSubmitAccumulativeRunnable.run(SwingWorker.java:814)
    在sun.swing.AccumulativeRunnable.run(AccumulativeRunnable.java:95)
    在javax.swing.SwingWorker $ DoSubmitAccumulativeRunnable.actionPerformed(SwingWorker.java:824)
    在javax.swing.Timer.fireActionPerformed(Timer.java:291)
    在javax.swing.Timer $ DoPostEvent.run(Timer.java:221)
    在java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
    在java.awt.EventQueue.dispatchEventImpl(EventQueue.java:677)
    在java.awt.EventQueue.access $ 000(EventQueue.java:85)
    在java.awt.EventQueue $ 1.run(EventQueue.java:638)
    在java.awt.EventQueue $ 1.run(EventQueue.java:636)
    在java.security.AccessController.doPrivileged(本地方法)
    在java.security.AccessControlContext $ 1.doIntersectionPrivilege(AccessControlContext.java:87)
    在java.awt.EventQueue.dispatchEvent(EventQueue.java:647)
    在java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296)
    在java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211)
    在java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201)
    在java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196)
    在java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188)
    在java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
引起:java.lang.ArrayIndexOutOfBoundsException:数组索引超出范围:2
    在java.util.Vector.get(Vector.java:694)
    在TableWithExecutor.changeTableValues(TableWithExecutor.java:64)
    在TableWithExecutor.access $ 100(TableWithExecutor.java:14)
    在TableWithExecutor $ MyTask.doInBackground(TableWithExecutor.java:92)
    在TableWithExecutor $ MyTask.doInBackground(TableWithExecutor.java:80)
    在javax.swing.SwingWorker $ 1.call(SwingWorker.java:277)
    在java.util.concurrent.FutureTask $ Sync.innerRun(FutureTask.java:303)
    在java.util.concurrent.FutureTask.run(FutureTask.java:138)
    在javax.swing.SwingWorker.run(SwingWorker.java:316)
    在java.util.concurrent.ThreadPoolExecutor $ Worker.runTask(ThreadPoolExecutor.java:886)
    在java.util.concurrent.ThreadPoolExecutor $ Worker.run(ThreadPoolExecutor.java:908)
    在java.lang.Thread.run(Thread.java:680)
 StartShedule:已开始 - >完成

完整代码:

 import java.awt.BorderLayout; import java.awt.Dimension; import java.awt.EventQueue; import java.awt.event.ActionEvent; import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeListener; import java.text.DateFormat; import java.util.Date; import java.util.List; import java.util.concurrent.Executor; import java.util.concurrent.Executors; import javax.swing.*; import javax.swing.table.*; /** @see https://stackoverflow.com/questions/7054627 */ public class TableWithExecutor extends JFrame { private static final int delay = 1000; private static final DateFormat df = DateFormat.getTimeInstance(); private String[] columnNames = {"Product", "Availability"}; private Object[][] data = {columnNames, columnNames, columnNames}; private DefaultTableModel model; private JTable table; private Executor executor = Executors.newCachedThreadPool(); private Timer timer; public TableWithExecutor() { model = new DefaultTableModel(data, columnNames); table = new JTable(model) { @Override public Class getColumnClass(int column) { return getValueAt(0, column).getClass(); } }; table.setDefaultRenderer(Date.class, new DefaultTableCellRenderer() { @Override protected void setValue(Object value) { setText((value == null) ? "" : df.format(value)); } }); table.setPreferredScrollableViewportSize(new Dimension(200, 100)); JScrollPane scrollPane = new JScrollPane(table); add(scrollPane, BorderLayout.CENTER); timer = new Timer(delay, startCycle()); timer.setRepeats(true); timer.start(); } private Action startCycle() { return new AbstractAction(MyTask.STARTSCHEDULE) { @Override public void actionPerformed(ActionEvent e) { executor.execute(new MyTask(MyTask.STARTSCHEDULE)); } }; } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { TableWithExecutor frame = new TableWithExecutor(); frame.setDefaultCloseOperation(EXIT_ON_CLOSE); frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } }); } private class MyTask extends SwingWorker<List<DateRecord>, DateRecord> { private static final String STARTSCHEDULE = "StartSchedule"; private String name = STARTSCHEDULE; MyTask(String name) { this.name = name; addPropertyChangeListener(new TaskListener(name)); } @Override protected List<DateRecord> doInBackground() throws Exception { for (int row = 0; row < model.getRowCount(); row++) { Date date = new Date(); date.setTime(date.getTime() + row * 1000); publish(new DateRecord(row, date)); } return null; } @Override protected void process(List<DateRecord> chunks) { for (DateRecord dr : chunks) { model.setValueAt(dr.date, dr.rowNumber, 1); } } @Override protected void done() { try { get(); } catch (Exception e) { e.printStackTrace(System.err); } } } private static class DateRecord { private int rowNumber; private Date date; public DateRecord(int recordNumber, Date date) { this.rowNumber = recordNumber; this.date = date; } } private static class TaskListener implements PropertyChangeListener { private String name; TaskListener(String name) { this.name = name; } @Override public void propertyChange(PropertyChangeEvent e) { System.out.println(name + ": " + e.getOldValue() + " -> " + e.getNewValue()); } } } 

我认为你遇到的问题是在后台线程中捕获的exception只有在处理完成时调用get()才会重新抛出。 这似乎是SwingWorker的常见问题。

您可以将您的done()函数更改为:

 @Override protected void done() { if (str.equals("StartShedule")) { try { get(); } catch (Exception ex) { // This exception was thrown during processing ex.printStackTrace(); } } } 

done()在事件派发线程上执行,所以你可以从那里显示你需要的任何错误信息。 我希望有一些帮助。