我需要通过List迭代,将List中的每个元素添加到一个新List中,并从原始列表中删除该元素。我有三个线程在同一个原始列表上运行相同的进程。 每个帖子都需要添加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)
谢谢大家!!
答案 0 :(得分:0)
一个线程通常不允许修改Collection,而另一个线程正在迭代它。见ConcurrentModificationException
答案 1 :(得分:0)
有一个Concurrent Queue实现应该做你想要的(你所描述的代码似乎更像是一个队列而不是列表)。
如果你必须使用一个列表(好吧,队列是一个列表,但也许你有特殊要求),你将不得不同步你的方法,这将使整个线程没有意义 - 但如果它&#39;那么这可能是他们想要教给你的东西......如果是这样的话,不要在列表上循环(迭代器将破灭)并将同步(列表)放在一起与列表交互的代码的每个部分。
另外一定要把你的阅读和删除内容放在同一个同步语句中 - 因为你编写的是防御性思考。任何另一个线程可以滑入的洞和“攻击”#34;你应该考虑一下!即使是像x ++这样的东西,如果它在2个线程中并且没有得到适当保护,也会搞砸。
答案 2 :(得分:0)
答案 3 :(得分:0)
我以为我会用我为改变这个问题所做的更改来更新这个问题。以下是更重要的代码更改:
static Queue<Book> library = new ConcurrentLinkedQueue<>();
public static boolean libraryHasBooks() {
if (library.isEmpty()) {
System.out.println("Closing Application");
System.out.println("The Library has : " + library);
librarian1.getResults();
librarian2.getResults();
librarian3.getResults();
System.exit(0);
}
return true;
}
private synchronized void removeBook() {
Iterator<Book> libraryIterator = library.iterator();
if (libraryIterator.hasNext()) {
libraryIterator.next();
library.poll();
}
}
public synchronized void performAction() {
for (int x = 1; x <= 3; x++) {
this.getBook();
this.removeBook();
this.getTotalValue();
this.getTotalBooks();
}
}
public void getResults() {
System.out.println();
System.out.println(this.getName() + ": Has " + this.getTotalBooks() +" books. "
+ " With a total value of $" + this.getTotalValue());
System.out.println(this.getName() + ": Has " + this.box.toString());
}
@Override
public void run() {
while(libraryHasBooks()) {
this.performAction();
try
{
Thread.sleep(sleepTime);
}
catch(InterruptedException e) { e.printStackTrace(); }
}
}