无法从 Future<?> 获取 ArrayIndexOutOfBoundsException和 SwingWorker 如果线程启动 Executor [英] Can&#39;t get ArrayIndexOutOfBoundsException from Future&lt;?&gt; and SwingWorker if thread starts Executor

查看:21
本文介绍了无法从 Future<?> 获取 ArrayIndexOutOfBoundsException和 SwingWorker 如果线程启动 Executor的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用 Executor 为 SwingWorker 进行了多线程处理,但我在那里错误地从 Vector 中识别出了错误的元素,看起来像这段代码完全忽略了 Vector 中不存在的元素

我的问题 -> 如何/是否可能以某种方式捕获此异常

简单的输出

运行:名称为:StartShedule 的线程状态,SwingWorker 状态为 STARTED名称为:StartShedule 的线程状态,SwingWorker 状态为 DONE名称为:StartShedule 的线程状态,SwingWorker 状态为 STARTED名称为:StartShedule 的线程状态,SwingWorker 状态为 DONE名称为:StartShedule 的线程状态,SwingWorker 状态为 STARTED名称为:StartShedule 的线程状态,SwingWorker 状态为 DONE构建成功(总时间:11 秒)

通过取消注释

//changeTableValues1();//取消注释获取 ArrayIndexOutOfBoundsException

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

运行:线程AWT-EventQueue-0"中的异常java.lang.ArrayIndexOutOfBoundsException:数组索引超出范围:2在 java.util.Vector.get(Vector.java:694)在 KondorExport.Util.Help.Table.TableWithExecutor.changeTableValues1(TableWithExecutor.java:70)在 KondorExport.Util.Help.Table.TableWithExecutor.access$100(TableWithExecutor.java:18)在 KondorExport.Util.Help.Table.TableWithExecutor$2.actionPerformed(TableWithExecutor.java:61)在 javax.swing.Timer.fireActionPerformed(Timer.java:271)在 javax.swing.Timer$DoPostEvent.run(Timer.java:201)在 java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)在 java.awt.EventQueue.dispatchEvent(EventQueue.java:597)在 java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:269)在 java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:184)在 java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:174)在 java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:169)在 java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:161)在 java.awt.EventDispatchThread.run(EventDispatchThread.java:122)名称为:StartShedule 的线程状态,SwingWorker 状态为 STARTED名称为:StartShedule 的线程状态,SwingWorker 状态为 DONE构建成功(总时间:10 秒)

来自代码

import java.awt.BorderLayout;导入 java.awt.event.ActionEvent;导入 java.beans.PropertyChangeEvent;导入 java.beans.PropertyChangeListener;导入 java.util.List;导入 java.util.Vector;导入 java.util.concurrent.Executor;导入 java.util.concurrent.Executors;导入 javax.swing.*;导入 javax.swing.table.*;公共类 TableWithExecutor 扩展 JFrame {private static final long serialVersionUID = 1L;private String[] columnNames = {"Narrative", "Description"};private Object[][] data = {{"About", "About"}, {"Add", "Add"}};私有 JTable 表;私有执行器执行器 = Executors.newCachedThreadPool();私人定时器 timerRun;私人 int 延迟 = 3000;私有向量fwDeals;私有向量fwDeals1;公共 TableWithExecutor() {DefaultTableModel 模型 = 新的 DefaultTableModel(data, columnNames);表 = 新 JTable(模型){private static final long serialVersionUID = 1L;@覆盖公共类 getColumnClass(int column) {返回 getValueAt(0, column).getClass();}};table.setPreferredScrollableViewportSize(table.getPreferredSize());JScrollPane scrollPane = new JScrollPane(table);添加(滚动窗格,BorderLayout.CENTER);prepareStartShedule();}私有无效prepareStartShedule(){timerRun = new javax.swing.Timer(delay, startCycle());timerRun.setRepeats(true);timerRun.start();}私人动作 startCycle() {return new AbstractAction("Start Shedule") {private static final long serialVersionUID = 1L;@覆盖public void actionPerformed(ActionEvent e) {executor.execute(new TableWithExecutor.MyTask("StartShedule"));//非美国东部时间//更改表值1();//取消注释获取 ArrayIndexOutOfBoundsException}};}私有无效changeTableValues1(){fwDeals1 = new Vector();fwDeals1.add("第一");//元素在(0)fwDeals1.add("Second");//ElementAt(1)checkDealsInDb1(fwDeals1.get(1), fwDeals1.get(2));}私人无效checkDealsInDb1(字符串Str,字符串Str1){table.getModel().setValueAt(Str, 0, 1);table.getModel().setValueAt(Str1, 1, 1);}私有无效changeTableValues(){fwDeals = new Vector();fwDeals.add("第一");//元素在(0)fwDeals.add("Second");//ElementAt(1)checkDealsInDb(fwDeals.get(1), fwDeals.get(2));}私人无效checkDealsInDb(字符串Str,字符串Str1){table.getModel().setValueAt(Str, 0, 1);table.getModel().setValueAt(Str1, 1, 1);}公共静态无效主(字符串 [] args){TableWithExecutor frame = new TableWithExecutor();frame.setDefaultCloseOperation(EXIT_ON_CLOSE);frame.setLocation(150, 150);框架.pack();frame.setVisible(true);}私有类 MyTask 扩展了 SwingWorker{私人字符串str;私人字符串名称Pr;我的任务(字符串 str){this.str = str;addPropertyChangeListener(new SwingWorkerCompletionWaiter(str, namePr));}@覆盖受保护的 Void doInBackground() 抛出异常 {如果(str.equals(StartShedule")){更改表值();}返回空;}@覆盖受保护的无效进程(列表<整数>进度){}@覆盖受保护的无效完成(){如果(str.equals(StartShedule")){}}}私有类 SwingWorkerCompletionWaiter 实现 PropertyChangeListener {私人字符串str;私人字符串名称Pr;SwingWorkerCompletionWaiter(String str, String namePr) {this.str = str;this.namePr = namePr;}SwingWorkerCompletionWaiter(字符串名称Pr){this.namePr = namePr;}@覆盖公共无效propertyChange(PropertyChangeEvent事件){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("Mame 的线程状态:" + str + ",SwingWorker 状态为" + 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());} 别的 {System.out.println("某些事情发生了错误,线程状态为名称:" + str);}}}}

在 done() 方法中添加了从 Future#get() 重新抛出的内容(@takteek 极好的建议)

@Override受保护的无效完成(){如果(str.equals(StartShedule")){尝试 {得到();//errLabel.setText(String.valueOf(get()));} catch (InterruptedException ie) {即.printStackTrace();} catch (ExecutionException ee) {ee.printStackTrace();}catch (IllegalStateException 是) {is.printStackTrace();}}}

但是输出仍然并且只有 Got exception,很难从这个 BlackBox 获得任何异常

运行:有异常名称为:StartShedule 的线程状态,SwingWorker 状态为 STARTED名称为:StartShedule 的线程状态,SwingWorker 状态为 DONE有异常名称为:StartShedule 的线程状态,SwingWorker 状态为 STARTED名称为:StartShedule 的线程状态,SwingWorker 状态为 DONE有异常名称为:StartShedule 的线程状态,SwingWorker 状态为 STARTED名称为:StartShedule 的线程状态,SwingWorker 状态为 DONE有异常名称为:StartShedule 的线程状态,SwingWorker 状态为 STARTED名称为:StartShedule 的线程状态,SwingWorker 状态为 DONE构建成功(总时间:13 秒)

解决方案

我不确定它增加了多少,但我得到了预期的 Caused by 使用 takteek 的 答案如下所示.我从命令行运行它以确保 IDE 没有帮助".

<前>$ java -cp build/classes TableWithExecutor开始时间:待定 -> 开始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(Native Method)在 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)开始时间:开始 -> 完成

完整代码:

import java.awt.BorderLayout;导入 java.awt.Dimension;导入 java.awt.EventQueue;导入 java.awt.event.ActionEvent;导入 java.beans.PropertyChangeEvent;导入 java.beans.PropertyChangeListener;导入 java.text.DateFormat;导入 java.util.Date;导入 java.util.List;导入 java.util.concurrent.Executor;导入 java.util.concurrent.Executors;导入 javax.swing.*;导入 javax.swing.table.*;/** @see https://stackoverflow.com/questions/7054627 */公共类 TableWithExecutor 扩展 JFrame {私有静态最终 int 延迟 = 1000;私有静态最终 DateFormat df = DateFormat.getTimeInstance();私人字符串[] columnNames = {产品",可用性"};私有对象[][] 数据 = {columnNames, columnNames, columnNames};私有 DefaultTableModel 模型;私有 JTable 表;私有执行器执行器 = Executors.newCachedThreadPool();私人定时器定时器;公共 TableWithExecutor() {模型 = 新的 DefaultTableModel(data, columnNames);表 = 新 JTable(模型){@覆盖公共类 getColumnClass(int column) {返回 getValueAt(0, column).getClass();}};table.setDefaultRenderer(Date.class, new DefaultTableCellRenderer() {@覆盖protected void setValue(Object value) {setText((value == null) ? "" : df.format(value));}});table.setPreferredScrollableViewportSize(new Dimension(200, 100));JScrollPane scrollPane = new JScrollPane(table);添加(滚动窗格,BorderLayout.CENTER);timer = new Timer(delay, startCycle());timer.setRepeats(true);定时器开始();}私人动作 startCycle() {返回新的 AbstractAction(MyTask.STARTSCHEDULE) {@覆盖public void actionPerformed(ActionEvent e) {executor.execute(new MyTask(MyTask.STARTSCHEDULE));}};}公共静态无效主(字符串 [] args){EventQueue.invokeLater(new Runnable() {@覆盖公共无效运行(){TableWithExecutor frame = new TableWithExecutor();frame.setDefaultCloseOperation(EXIT_ON_CLOSE);框架.pack();frame.setLocationRelativeTo(null);frame.setVisible(true);}});}私有类 MyTask 扩展了 SwingWorker, DateRecord>{private static final String STARTSCHEDULE = "StartSchedule";私人字符串名称 = STARTSCHEDULE;我的任务(字符串名称){this.name = 名称;addPropertyChangeListener(new TaskListener(name));}@覆盖受保护的列表<DateRecord>doInBackground() 抛出异常 {for (int row = 0; row < model.getRowCount(); row++) {日期日期=新日期();date.setTime(date.getTime() + row * 1000);发布(新日期记录(行,日期));}返回空;}@覆盖protected void process(List chunks) {for (DateRecord dr : chunks) {model.setValueAt(dr.date, dr.rowNumber, 1);}}@覆盖受保护的无效完成(){尝试 {得到();} 捕获(异常 e){e.printStackTrace(System.err);}}}私有静态类 DateRecord {私人 int rowNumber;私人日期;公共日期记录(整数记录编号,日期日期){this.rowNumber = recordNumber;this.date = 日期;}}私有静态类 TaskListener 实现 PropertyChangeListener {私人字符串名称;任务监听器(字符串名称){this.name = 名称;}@覆盖public void propertyChange(PropertyChangeEvent e) {System.out.println(name + ": "+ e.getOldValue() + " -> " + e.getNewValue());}}}

I play with multitreading for SwingWorker by using Executor, and I'm there by mistake identified wrong elements from the Vector, looks like as this code pretty ignores that element in Vector doesn't exist

my question -> how to/is possible to catch this exception(s) some way

simple output

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)

by uncomment

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

everything is correct, I get ArrayIndexOutOfBoundsException and output is

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)

from code

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);
            }
        }
    }
}

EDIT:

added re-thrown from Future#get() in done() method (by @takteek excellent suggestion)

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

but output is still and only Got exception, would be so hard to get any exception(s) from this 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)

解决方案

I'm not sure it adds much, but I got the expected Caused by using the variation of takteek's answer shown below. I ran it from the command line to be sure the IDE wasn't "helping".

$ java -cp build/classes TableWithExecutor
StartShedule: PENDING -> STARTED
java.util.concurrent.ExecutionException: java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 2
    at java.util.concurrent.FutureTask$Sync.innerGet(FutureTask.java:222)
    at java.util.concurrent.FutureTask.get(FutureTask.java:83)
    at javax.swing.SwingWorker.get(SwingWorker.java:582)
    at TableWithExecutor$MyTask.done(TableWithExecutor.java:103)
    at javax.swing.SwingWorker$5.run(SwingWorker.java:717)
    at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.run(SwingWorker.java:814)
    at sun.swing.AccumulativeRunnable.run(AccumulativeRunnable.java:95)
    at javax.swing.SwingWorker$DoSubmitAccumulativeRunnable.actionPerformed(SwingWorker.java:824)
    at javax.swing.Timer.fireActionPerformed(Timer.java:291)
    at javax.swing.Timer$DoPostEvent.run(Timer.java:221)
    at java.awt.event.InvocationEvent.dispatch(InvocationEvent.java:209)
    at java.awt.EventQueue.dispatchEventImpl(EventQueue.java:677)
    at java.awt.EventQueue.access$000(EventQueue.java:85)
    at java.awt.EventQueue$1.run(EventQueue.java:638)
    at java.awt.EventQueue$1.run(EventQueue.java:636)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.security.AccessControlContext$1.doIntersectionPrivilege(AccessControlContext.java:87)
    at java.awt.EventQueue.dispatchEvent(EventQueue.java:647)
    at java.awt.EventDispatchThread.pumpOneEventForFilters(EventDispatchThread.java:296)
    at java.awt.EventDispatchThread.pumpEventsForFilter(EventDispatchThread.java:211)
    at java.awt.EventDispatchThread.pumpEventsForHierarchy(EventDispatchThread.java:201)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:196)
    at java.awt.EventDispatchThread.pumpEvents(EventDispatchThread.java:188)
    at java.awt.EventDispatchThread.run(EventDispatchThread.java:122)
Caused by: java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 2
    at java.util.Vector.get(Vector.java:694)
    at TableWithExecutor.changeTableValues(TableWithExecutor.java:64)
    at TableWithExecutor.access$100(TableWithExecutor.java:14)
    at TableWithExecutor$MyTask.doInBackground(TableWithExecutor.java:92)
    at TableWithExecutor$MyTask.doInBackground(TableWithExecutor.java:80)
    at javax.swing.SwingWorker$1.call(SwingWorker.java:277)
    at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
    at java.util.concurrent.FutureTask.run(FutureTask.java:138)
    at javax.swing.SwingWorker.run(SwingWorker.java:316)
    at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:886)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:908)
    at java.lang.Thread.run(Thread.java:680)
StartShedule: STARTED -> DONE

Full code:

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

这篇关于无法从 Future<?> 获取 ArrayIndexOutOfBoundsException和 SwingWorker 如果线程启动 Executor的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆