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

查看:30
本文介绍了无法从 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 = {"叙述", "描述"};私有对象[][] 数据 = {{关于"、关于"}、{添加"、添加"}};私有 JTable 表;private Executor executor = Executors.newCachedThreadPool();私人计时器计时器运行;私人int延迟= 3000;私有向量<字符串>fwDeals;私有向量<字符串>fwDeals1;公共 TableWithExecutor() {DefaultTableModel 模型 = new 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;@覆盖公共无效actionPerformed(ActionEvent e){executor.execute(new TableWithExecutor.MyTask("StartShedule"));//非美国东部时间//changeTableValues1();//取消注释获取 ArrayIndexOutOfBoundsException}};}私人无效changeTableValues1(){fwDeals1 = 新向量<字符串>();fwDeals1.add("第一");//ElementAt(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 = 新向量<字符串>();fwDeals.add("第一");//ElementAt(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<Void, Integer>{私有字符串 str;私有字符串名称Pr;我的任务(字符串字符串){这个.str = str;addPropertyChangeListener(new SwingWorkerCompletionWaiter(str, namePr));}@覆盖protected Void doInBackground() 抛出异常 {if (str.equals("StartShedule")) {更改表值();}返回空值;}@覆盖受保护的无效进程(列表<整数>进度){}@覆盖受保护的无效完成(){if (str.equals("StartShedule")) {}}}私有类 SwingWorkerCompletionWaiter 实现 PropertyChangeListener {私有字符串 str;私有字符串名称Pr;SwingWorkerCompletionWaiter(String str, String namePr) {这个.str = str;this.namePr = namePr;}SwingWorkerCompletionWaiter(String namePr) {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("SomeThing Wrong 发生,线程状态为 :" + str);}}}}

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

@Override受保护的无效完成(){if (str.equals("StartShedule")) {尝试 {得到();//errLabel.setText(String.valueOf(get()));} 捕捉(InterruptedException 即){即.printStackTrace();} 捕捉(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 秒)

解决方案

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

<上一页>$ java -cp 构建/类 TableWithExecutorStartShedule:待定 -> 已开始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)StartShedule:开始 -> 完成

完整代码:

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;私有静态最终日期格式 df = DateFormat.getTimeInstance();私有字符串[] columnNames = {产品",可用性"};私有对象[][] 数据 = {columnNames, columnNames, columnNames};私有 DefaultTableModel 模型;私有 JTable 表;private Executor executor = Executors.newCachedThreadPool();私人定时器定时器;公共 TableWithExecutor() {model = new DefaultTableModel(data, columnNames);表 = 新 JTable(模型){@覆盖公共类 getColumnClass(int column) {返回 getValueAt(0, column).getClass();}};table.setDefaultRenderer(Date.class, new DefaultTableCellRenderer() {@覆盖受保护的无效setValue(对象值){setText((value == null) ? "" : df.format(value));}});table.setPreferredScrollableViewportSize(new Dimension(200, 100));JScrollPane scrollPane = new JScrollPane(table);添加(滚动窗格,BorderLayout.CENTER);timer = new Timer(延迟,startCycle());timer.setRepeats(true);计时器.start();}私人动作 startCycle() {返回新的 AbstractAction(MyTask.STARTSCHEDULE) {@覆盖公共无效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<List<DateRecord>, DateRecord>{私有静态最终字符串 STARTSCHEDULE = "StartSchedule";私有字符串名称 = STARTSCHEDULE;我的任务(字符串名称){this.name = 名称;addPropertyChangeListener(new TaskListener(name));}@覆盖受保护列表<日期记录>doInBackground() 抛出异常 {for (int row = 0; row < model.getRowCount(); row++) {日期日期 = 新日期();date.setTime(date.getTime() + 行 * 1000);发布(新日期记录(行,日期));}返回空值;}@覆盖受保护的无效进程(列出块){对于(日期记录博士:块){model.setValueAt(dr.date, dr.rowNumber, 1);}}@覆盖受保护的无效完成(){尝试 {得到();} 捕获(异常 e){e.printStackTrace(System.err);}}}私有静态类 DateRecord {私人 int 行号;私人日期日期;公共日期记录(整数记录编号,日期日期){this.rowNumber = 记录号;this.date = 日期;}}私有静态类 TaskListener 实现 PropertyChangeListener {私有字符串名称;任务监听器(字符串名称){this.name = 名称;}@覆盖公共无效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&lt;?&gt; 获取 ArrayIndexOutOfBoundsException和 SwingWorker 如果线程启动 Executor的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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