我对java很新,我实际上是在编写一个键盘记录程序并定期写入文件。每次用户按下一个键时,它都会实例化一个NativeKeyEvent,它调用' paramString()'并将信息作为字符串添加到下面的arraylist中......
public static ArrayList<String> stringArray = new ArrayList<String>();
public synchronized String paramString() {
StringBuilder param = new StringBuilder(255);
// other code
stringArray.add(param.toString());
}
然后在每个时间间隔传递字符串数组并将其写入下面的TimerTask线程中的文件...
public class SaveToArrayAndWriteTask extends TimerTask {
private ArrayList<String> anotherArray = NativeKeyEvent.stringArray;
private static String str;
@Override
public synchronized void run() {
openFile();
writeToFile(anotherArray);
closeFile();
}
private static synchronized void writeToFile(ArrayList<String> localArray) {
Iterator<String> iterator = localArray.iterator();
try {
while (iterator.hasNext()) {
str = iterator.next().toString();
output.format("%s\n", str);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
行&#39; str = iterator.next()。toString();&#39;如果它在程序记录/添加另一个键击时尝试迭代arraylist将其写入文件,则抛出异常。我想通过将stringArray(正在被修改)放入anotherArray并将其作为参数传递将阻止这种情况发生。正如您所看到的,我已尝试使用synchronized关键字,我也尝试将其放入另一个线程,并在stackoverflow上阅读了其他各种帖子,但无济于事。
解决此问题的最佳方法是什么?
答案 0 :(得分:0)
您没有复制ArrayList,只是对同一个ArrayList进行了另一个引用。
private ArrayList<String> anotherArray = NativeKeyEvent.stringArray;
应该是这样的:
private ArrayList<String> copy = new ArrayList<>(NativeKeyEvent.stringArray);
这将创建一个 new ArrayList,其元素与NativeKeyEvent.stringArray
相同。
我建议使用getter而不是将stringArray
公开为公共变量。 getter应该复制stringArray
并返回它。这样,stringArray
的任何消费者都将在副本上运行,并且无法修改列表。
答案 1 :(得分:0)
我想通过将stringArray(正在修改)放入anotherArray
private ArrayList<String> anotherArray = NativeKeyEvent.stringArray;
不创建新的ArrayList。 anotherArray仍然引用同一个对象。 您需要创建一个包含stringArray元素的新ArrayList。
private ArrayList<String> anotherArray = new ArrayList<>(NativeKeyEvent.stringArray);
答案 2 :(得分:0)
一般来说,如果您在迭代时修改某个集合,那么您将获得ConcurrentModificationException
。
您有两种选择:
困难的方法:同步访问列表,以便其他线程在您重复迭代时阻止
简单方法:使用CopyOnWriteArrayList
包中的java.util.concurrent
列表实现,它为您完成所有艰苦工作
public static ArrayList<String> stringArray = new CopyOnWriteArrayList<String>();
那就是它。没有更多需要,您可以删除所有同步。