我需要迭代一个列表,将列表中的每个元素添加到一个新列表中,并从原始列表中删除该元素。我有三个线程在同一个原始列表上运行相同的进程。每个线程需要添加3本书,然后删除这3本书,每一本书都要经过循环。
这是我的代码:
public class BookBoxer {
static List<Book> library = new ArrayList<>();
static Librarian librarian1 = new Librarian();
static Thread thread1 = new Thread(librarian1, "librarian1");
static Librarian librarian2 = new Librarian();
static Thread thread2 = new Thread(librarian2, "librarian2");
static Librarian librarian3 = new Librarian();
static Thread thread3 = new Thread(librarian3, "librarian3");
public static void main(String[] args) {
buldLibrary();
thread1.start();
thread2.start();
thread3.start();
System.out.println("Librarian 1: total books: "+ librarian1.getTotalBooks()+
" || total value: $" + librarian1.getTotalValue());
System.out.println("librarian 1 book: " + librarian1.box.toString());
System.out.println();
System.out.println("Librarian 2: total books: "+ librarian2.getTotalBooks()+
" || total value: $" + librarian2.getTotalValue());
System.out.println("librarian 2 book: " + librarian2.box.toString());
System.out.println();
System.out.println("Librarian 3: total books: "+ librarian3.getTotalBooks()+
" || total value: $" + librarian3.getTotalValue());
System.out.println("librarian 3 book: " + librarian3.box.toString());
System.out.println();
System.out.println("This is the new library " + library);
System.out.println("The library has books: " + libraryHasBooks());
}
public static void buldLibrary() {
int i = 1;
while(i < 101) {
Book book = new Book("Book #");
library.add(book);
book.incrementPrice();
System.out.println(book.toString());
i++;
}
}
public static boolean libraryHasBooks() {
if(library.isEmpty()) {
return false;
}
return true;
}
static class Librarian implements Runnable {
private static long sleepTime = ((long)(Math.random() * 1000));
private double totalValue;
private int totalBooks = 0;
List<Book> box = new ArrayList<>();
private void getBook(List<Book> aLibrary) {
Iterator<Book> libraryIterator = aLibrary.iterator();
if(libraryIterator.hasNext()) {
box.add(libraryIterator.next());
}
}
private void removeBook(List<Book> aLibrary) {
Iterator<Book> libraryIterator = aLibrary.iterator();
if(libraryIterator.hasNext()) {
libraryIterator.next();
libraryIterator.remove();
}
}
private double getTotalValue() {
Iterator<Book> boxIterator = box.iterator();
while(boxIterator.hasNext()) {
totalValue += boxIterator.next().getPrice();
}
return totalValue;
}
private int getTotalBooks() {
for(Book i : box) {
totalBooks++;
}
return totalBooks;
}
public void performAction() {
for(int x = 1; x <= 3; x++) {
this.getBook(library);
this.removeBook(library);
}
}
@Override
public void run() {
while(libraryHasBooks())
{
this.performAction();
try
{
Thread.sleep(sleepTime);
} catch (InterruptedException e) { e.printStackTrace(); }
}
}
}
}这是我的输出:
Librarian 1: total books: 3 || total value: $3.75
librarian 1 book: [Name: Book #1 Price: $1.0, Name: Book #2 Price: $1.25, Name: Book #3 Price: $1.5]
Librarian 2: total books: 3 || total value: $6.0
librarian 2 book: [Name: Book #4 Price: $1.75, Name: Book #5 Price: $2.0, Name: Book #6 Price: $2.25]
Librarian 3: total books: 3 || total value: $8.25
librarian 3 book: [Name: Book #7 Price: $2.5, Name: Book #8 Price: $2.75, Name: Book #9 Price: $3.0]
This is the new library [Name: Book #10 Price: $3.25, Name: Book #11 Price: $3.5, Name: Book #12 Price: $3.75, Name: Book #13 Price: $4.0, Name: Book #14 Price: $4.25, Name: Book #15 Price: $4.5, Name: Book #16 Price: $4.75, Name: Book #17 Price: $5.0, Name: Book #18 Price: $5.25, Name: Book #19 Price: $5.5,....................
The library has books: true
Exception in thread "librarian3" java.util.ConcurrentModificationException
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:819)
at java.util.ArrayList$Itr.next(ArrayList.java:791)
at com.github.salvadore_jefferson.libraryapp.BookBoxer$Librarian.getBook(BookBoxer.java:80)
at com.github.salvadore_jefferson.libraryapp.BookBoxer$Librarian.performAction(BookBoxer.java:109)
at com.github.salvadore_jefferson.libraryapp.BookBoxer$Librarian.run(BookBoxer.java:118)
at java.lang.Thread.run(Thread.java:722)谢谢大家!!
发布于 2015-08-06 16:57:32
有一个并发队列实现应该做您想做的事情(您的代码看起来更像是一个队列,而不是一个列表)。
如果你必须使用一个列表(嗯,一个队列是一个列表,但也许你有特殊的要求),你将不得不同步你的方法,这将使整个线程的事情变得毫无意义--但是如果这是一个练习,也许这就是他们想教你的.如果是这样的话,不要在列表上循环(迭代器会关闭),并在与列表交互的代码的每一部分周围放置一个同步(列表)。
同时,一定要将读取和删除放在相同的同步语句中--在编写代码时,要考虑防御。任何一个洞,其中的另一个线程可能滑入和“攻击”,你应该考虑!即使是像x++这样的东西,如果是在两个线程中,并且没有得到适当的保护,也可能会被搞砸。
发布于 2015-08-06 16:39:54
一般不允许一个线程修改一个集合,而另一个线程则在它上迭代。请参阅ConcurrentModificationException
发布于 2015-08-06 18:00:33
https://stackoverflow.com/questions/31861120
复制相似问题