首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在线程内迭代

在线程内迭代
EN

Stack Overflow用户
提问于 2015-08-06 16:29:24
回答 4查看 82关注 0票数 0

我需要迭代一个列表,将列表中的每个元素添加到一个新列表中,并从原始列表中删除该元素。我有三个线程在同一个原始列表上运行相同的进程。每个线程需要添加3本书,然后删除这3本书,每一本书都要经过循环。

这是我的代码:

代码语言:javascript
复制
    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(); }
        }
      }

  }
}

这是我的输出:

代码语言:javascript
复制
    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)

谢谢大家!!

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2015-08-06 16:57:32

有一个并发队列实现应该做您想做的事情(您的代码看起来更像是一个队列,而不是一个列表)。

如果你必须使用一个列表(嗯,一个队列是一个列表,但也许你有特殊的要求),你将不得不同步你的方法,这将使整个线程的事情变得毫无意义--但是如果这是一个练习,也许这就是他们想教你的.如果是这样的话,不要在列表上循环(迭代器会关闭),并在与列表交互的代码的每一部分周围放置一个同步(列表)。

同时,一定要将读取和删除放在相同的同步语句中--在编写代码时,要考虑防御。任何一个洞,其中的另一个线程可能滑入和“攻击”,你应该考虑!即使是像x++这样的东西,如果是在两个线程中,并且没有得到适当的保护,也可能会被搞砸。

票数 0
EN

Stack Overflow用户

发布于 2015-08-06 16:39:54

一般不允许一个线程修改一个集合,而另一个线程则在它上迭代。请参阅ConcurrentModificationException

票数 0
EN

Stack Overflow用户

发布于 2015-08-06 18:00:33

  1. 您可以通过同步列表来完成它。
  2. 您可以等待一个公共共享对象。
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/31861120

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档