Исключение выходит если запускаю в потоке, а без потока не появляется вроде бы. Как подправить чтоб без бага было.
Exception in thread "AWT-EventQueue-0" java.lang.IndexOutOfBoundsException: Index: 1, Size: 0
at java.util.LinkedList.checkElementIndex(Unknown Source)
at java.util.LinkedList.get(Unknown Source)
at ta.MyListModel.getElementAt(MyListModel.java:31)
at ta.MyListModel.getElementAt(MyListModel.java:1)
at javax.swing.plaf.basic.BasicListUI.updateLayoutState(Unknown Source)
at javax.swing.plaf.basic.BasicListUI.maybeUpdateLayoutState(Unknown Source)
at javax.swing.plaf.basic.BasicListUI.getPreferredSize(Unknown Source)
at javax.swing.JComponent.getPreferredSize(Unknown Source)
at javax.swing.ScrollPaneLayout.layoutContainer(Unknown Source)
at java.awt.Container.layout(Unknown Source)
at java.awt.Container.doLayout(Unknown Source)
at java.awt.Container.validateTree(Unknown Source)
at java.awt.Container.validate(Unknown Source)
at javax.swing.RepaintManager$3.run(Unknown Source)
at javax.swing.RepaintManager$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at javax.swing.RepaintManager.validateInvalidComponents(Unknown Source)
at javax.swing.RepaintManager$ProcessingRunnable.run(Unknown Source)
at java.awt.event.InvocationEvent.dispatch(Unknown Source)
at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
at java.awt.EventQueue.access$500(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.awt.EventQueue$3.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.security.ProtectionDomain$JavaSecurityAccessImpl.doIntersectionPrivilege(Unknown Source)
at java.awt.EventQueue.dispatchEvent(Unknown Source)
at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
at java.awt.EventDispatchThread.run(Unknown Source)
Класс модели
package ta;
import java.math.BigDecimal;
import java.util.LinkedList;
import javax.swing.AbstractListModel;
public class MyListModel extends AbstractListModel<String>{
private static final long serialVersionUID = 1L;
private LinkedList<BigDecimal> listBets;
public LinkedList<BigDecimal> getListBets() {
return listBets;
}
public void setListBets(LinkedList<BigDecimal> listBets) {
this.listBets = listBets;
}
public MyListModel(LinkedList<BigDecimal> list) {
setList(list);
}
public void add(BigDecimal value){
getList().add(value);
refresh();
}
public String getElementAt(int index) {
return String.format("%.8f", getList().get(index));
}
public int getSize() {
return getList().size();
}
public LinkedList<BigDecimal> getList(){
return listBets;
}
public void setList(LinkedList<BigDecimal> list){
this.listBets = list;
refresh();
}
public void clear() {
getList().clear();
refresh();
}
public void removeSide() {
getList().removeLast();
getList().removeFirst();
refresh();
}
void removeLast(){
getList().removeLast();
refresh();
}
public void refresh() {
fireContentsChanged(this, 0, getSize());
}
}
Класс с методом main
package ta;
import java.awt.EventQueue;
import javax.swing.JFrame;
import javax.swing.JPanel;
import java.awt.BorderLayout;
import java.awt.GridLayout;
import java.util.LinkedList;
import java.util.NoSuchElementException;
import java.util.Random;
import java.util.Scanner;
import javax.swing.JTextArea;
import javax.swing.JScrollPane;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JButton;
import java.awt.event.ActionListener;
import java.math.BigDecimal;
import java.text.ParseException;
import java.awt.event.ActionEvent;
public class TA {
private JFrame frame;
private MyListModel listModelBets;
private JList<String> list;
private JTextArea textArea;
private final String defaultBets = "0.00000001\n0.00000001\n0.00000001\n0.00000001\n0.00000001";
private final boolean win = true;
private final boolean lose = false;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
TA window = new TA();
window.frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the application.
*/
public TA() {
listModelBets = new MyListModel(new LinkedList<>());
initialize();
}
/**
* Initialize the contents of the frame.
*/
private void initialize() {
frame = new JFrame();
frame.setBounds(100, 100, 450, 300);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.getContentPane().setLayout(new BorderLayout(0, 0));
JPanel panel_2 = new JPanel();
frame.getContentPane().add(panel_2);
panel_2.setLayout(new GridLayout(0, 2, 0, 0));
JPanel panel_1 = new JPanel();
panel_2.add(panel_1);
panel_1.setLayout(new BorderLayout(0, 0));
JScrollPane scrollPane = new JScrollPane();
panel_1.add(scrollPane);
textArea = new JTextArea(defaultBets);
scrollPane.setViewportView(textArea);
JPanel panel = new JPanel();
panel_2.add(panel);
panel.setLayout(new BorderLayout(0, 0));
JScrollPane scrollPane_1 = new JScrollPane();
panel.add(scrollPane_1);
list = new JList<String>(listModelBets);
scrollPane_1.setViewportView(list);
JPanel panel_3 = new JPanel();
frame.getContentPane().add(panel_3, BorderLayout.SOUTH);
JButton btnNewButton_1 = new JButton("Clear");
btnNewButton_1.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
listModelBets.clear();
}
});
panel_3.add(btnNewButton_1);
JButton btnPlay = new JButton("Play");
btnPlay.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
Thread th = new Thread(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
boolean result = play();
if (result) {
if (listModelBets.getSize() == 1) {
listModelBets.removeLast();
} else if (listModelBets.getSize() > 1) {
listModelBets.removeSide();
}
} else {
listModelBets.add(getBet());
}
}
}
});
th.start();
}
});
panel_3.add(btnPlay);
}
void addBets() {
Scanner sc = new Scanner(textArea.getText());
sc.useDelimiter("\\n");
while (sc.hasNext()) {
String s = sc.next();
if (s != null && !s.equals("")) {
try {
BigDecimal b = new BigDecimal(s);
listModelBets.add(b);
} catch (NumberFormatException ex) {
// JOptionPane.showMessageDialog(frame, "Enter number
// value.\nSample 0.00000001");
}
}
}
sc.close();
}
boolean play() {
Random rnd = new Random();
return rnd.nextBoolean();
}
BigDecimal getBet() {
BigDecimal sum = null;
if (listModelBets.getSize() > 0) {
sum = calcSum();
} else {
addBets();
sum = calcSum();
}
return sum;
}
BigDecimal calcSum() {
BigDecimal sum = null;
try {
BigDecimal first = listModelBets.getList().getFirst();
BigDecimal last = listModelBets.getList().getLast();
sum = first.add(last);
} catch (NoSuchElementException ex) {
// stopGame();
JOptionPane.showMessageDialog(frame, "Enter number value\nin editor bets.\nSample 0.00000001");
}
return sum;
}
}
Проблема ваша заключается в том, что модель MyListModel
, не является потоко-безопасной. Но вы работает с ней при этом из разных потоков.
В момент получения размера списка и получения элементов, другой поток успевает удалить эти самые элементы. Поэтому и возникает ошибка.
Вижу несколько решений данной проблемы:
сделать модель thread-safe
, самые простой способ это сделать, заменить LinkedList
на альтернативу из пакета java.util.concurrent
либо объявить методы synchronized
.
Другое решение, изменять модель в одном потоке. Т.к. получения элементов происходит из потока UI
, то и удаление следует сделать из него же. Для этого требуется операции удаления делать следующим образом:
for (int i = 0; i < 1000; i++) {
boolean result = play();
try {
SwingUtilities.invokeAndWait(() -> {
if (result) {
if (listModelBets.getSize() == 1) {
listModelBets.removeLast();
} else if (listModelBets.getSize() > 1) {
listModelBets.removeSide();
}
} else {
listModelBets.add(getBet());
}
});
} catch (Exception e) {
e.printStackTrace();
}
}
Кофе для программистов: как напиток влияет на продуктивность кодеров?
Рекламные вывески: как привлечь внимание и увеличить продажи
Стратегії та тренди в SMM - Технології, що формують майбутнє сьогодні
Выделенный сервер, что это, для чего нужен и какие характеристики важны?
Современные решения для бизнеса: как облачные и виртуальные технологии меняют рынок
Прошу посоветовать книги по олимпиадному (школьному) программированию и вообще, что стоит учить, на данный момент читаю книгу Роберта Седжевика...
Не работает перенос строки в textarea в ipad(safari), по-разному пробовал