Im trying to make a simple gui app that starts a long process that can be started and stopped. The process generates random numbers and displays them in a JList. As numbers are being displayed (i.e. process is started), user can select a number from JList and delete. gui and uml http://mypages.valdosta.edu/dgibson/courses/cs4322/post.jpgI'm interested to know what improvements I could make to my approach. (And yes, I need to read TrashGod's posts on EDT and SwingWorker, I will!)public class MVC {    public static void main(String[] args) {        EventQueue.invokeLater(new Runnable() {            public void run() {                create();            }        });    }    private static void create() {        RandomNumberModel model = new RandomNumberModel();        Controller controller = new Controller(model);        View view = new View(controller);        controller.setView(view);        JFrame f = new JFrame(EDT & Long Thread);        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);        f.add(view);        f.pack();        f.setLocationRelativeTo(null);        f.setVisible(true);    }}public class View extends JPanel {    JList list;    DefaultListModel<Double> listModel;    JTextArea area;    JTextField field;    JButton btnGenerate = new JButton(Start Generation);    JButton btnStop = new JButton(Stop Generation);    JButton btnDelete = new JButton(Delete selected);    Controller controller;    public View(Controller controller) {        this.controller = controller;        this.setSize(new Dimension(600, 300));        // Create GUI components        listModel = new DefaultListModel<Double>();        list = new JList(listModel);        area = new JTextArea();        btnStop.setEnabled(false);        btnGenerate.addActionListener(controller);        btnStop.addActionListener(controller);        btnDelete.addActionListener(controller);        // Assemble GUI components        JPanel buttonPanel = new JPanel();        buttonPanel.add(btnGenerate);        buttonPanel.add(btnStop);        JPanel listPanel = new JPanel();        listPanel.setLayout(new BorderLayout());        listPanel.add(new JScrollPane(list));        listPanel.add(btnDelete, BorderLayout.SOUTH);        this.setLayout(new BorderLayout());        this.add(listPanel, BorderLayout.WEST);        this.add(buttonPanel, BorderLayout.SOUTH);        this.add(new JScrollPane(area));    }}public class Controller implements ActionListener {    static class ControlException extends Exception {}    static class StopGenException extends ControlException {}    View view;    RandomNumberModel model;    Thread thread = null;    volatile boolean isStopGen = false;    public Controller(RandomNumberModel model) {        this.model = model;    }    public void setView(View view) {        this.view = view;    }    public void actionPerformed(ActionEvent e) {        try {            if (view.btnGenerate.getActionCommand().equals(                    e.getActionCommand())) {                view.listModel.clear();                startNumGen();            } else if (view.btnStop.getActionCommand().equals(                    e.getActionCommand())) {                stopNumGen();            } else if (view.btnDelete.getActionCommand().equals(                    e.getActionCommand())) {                deleteElement();            }        }         catch (ControlException exc) {            System.out.println(exc);        }    }    public void startNumGen() throws ControlException {        thread = new Thread(new Runnable() {            public void run() {                try {                    doGeneration();                }                catch (ControlException exc) {                    System.out.println(Stopped  + exc);                }                 catch (InterruptedException exc) {                    System.out.println(Interrupted  + exc);                }                 finally {                    view.btnGenerate.setEnabled(true);                    view.btnStop.setEnabled(false);                    isStopGen = false;                }            }        });        view.btnGenerate.setEnabled(false);        view.btnStop.setEnabled(true);        thread.start();    }    private void doGeneration() throws StopGenException, InterruptedException {        for(int i=0; i<10; i++) {            if( isStopGen) {                throw new StopGenException();            }            final double val = model.getRandomNum();            EventQueue.invokeLater(new Runnable() {                public void run() {                    view.listModel.addElement(val);                }            });        }    }    public void stopNumGen() {        System.out.println(Stop generation);        isStopGen = true;    }    public void deleteElement() {        System.out.println(Delete number);        int indices[] = view.list.getSelectedIndices();        for (int i = 0; i < indices.length; i++) {            final int index = indices[indices.length - 1 - i];            System.out.print(Index:  + index);            double val = view.listModel.get(index);            System.out.println(, Deleted val:  + val);            EventQueue.invokeLater(new Runnable() {                    public void run() {                    view.listModel.remove(index);                }            });        }    }}public class RandomNumberModel {    public double getRandomNum() throws InterruptedException {        Thread.sleep(500);        return Math.random();    }}
Long Thread & EDT
java;thread safety;swing
AFAIK and according to Wikipedia:all user interface components should be created and accessed only from the AWT event dispatch thread.including view.list.getSelectedIndices() in the deleteElement() method. The good news is that the actionPerformed event handler (which calls deleteElement()) is already runned by this thread so it's fine but you could get rid of the EventQueue.invokeLater and call view.listModel.remove(index) directly there.The index/indices manipulation is not so convenient in the deleteElement() method:final int index = indices[indices.length - 1 - i];It took a while to figure out what it is doing and this is needed becase removing an element from a list shifts the indexes of elements after the removed one so you have to remove them in reversed order.I'd simply reverse the array and use a foreach loop:ArrayUtils.reverse(indices);for (final int elementIndex: indices) {    view.listModel.remove(elementIndex);}ArrayUtils is from Apache Commons Lang. (It's open-source so you can copy-paste that method to your code if you don't want to include a library only for one helper method.)