在 ArrayList 上工作的两种方法的同步

Synchronization of two method which work on ArrayList

我有 Sum class, Creator class, Item class 和 主要 Creator 创建随机项目并将它们添加到 Item class 中的 ArrayList。 Sum class 读取项目并对所有项目的权重求和。在 Main class 中,我在多个线程 CreatorSum 中启动。 classes 都实现了 Runnable 并覆盖了 运行 方法。 200 created are items into 打印在控制台中。

如何同步这些方法? 当我启动线程时,Sum 中的方法首先结束,returns 权重为 0,然后创建者创建 40 000 个随机项目。我将创建项目,同时对它们的所有权重求和,最后 Return 创建了多少项目以及所有项目的权重。

求和class方法:

@Override
    public synchronized void run() {

        for(Towar x: Towar.list){
            try {
                Thread.currentThread().wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            counter++;
            sum+=x.getWaga();
            if(counter%100==0){
                System.out.println("Sum of "+counter+" items");
            }
        }
        System.out.println("Total weight of Items: "+sum);
    }

创作者class方法:

@Override
    public void run() {
        reader=new Scanner(text);
        while(reader.hasNextLine()){
            counter++;
            String[] x=reader.nextLine().split("_");
            synchronized (Towar.getList()){
                Towar.add(new Towar(x[0], Integer.parseInt(x[1])));
                Towar.list.notify();
                if(counter%200==0){
                    System.out.println("Created "+counter+" items");
                }
            }

        }
        System.out.println("Created in total: "+counter+" items");
    }

BlockingQueue

我建议使用 BlockingQueue interface, instead of ArrayList. A BlockingQueue is thread-safe.

的实现

引用 Javadoc:

BlockingQueue implementations are thread-safe. All queuing methods achieve their effects atomically using internal locks or other forms of concurrency control. However, the bulk Collection operations addAll, containsAll, retainAll and removeAll are not necessarily performed atomically unless specified otherwise in an implementation. So it is possible, for example, for addAll(c) to fail (throwing an exception) after adding only some of the elements in c.

示例代码

 class Producer implements Runnable {
   private final BlockingQueue queue;
   Producer(BlockingQueue q) { queue = q; }
   public void run() {
        reader=new Scanner(text);
        while(reader.hasNextLine()){
            counter++;
            String[] x=reader.nextLine().split("_");
            q.put(new Towar(x[0], Integer.parseInt(x[1])));
            if(counter%200==0){
              System.out.println("Created "+counter+" items");
            }
        }
        q.put(null);
        System.out.println("Created in total: "+counter+" items");
   }
 }

 class Consumer implements Runnable {
   private final BlockingQueue queue;
   Consumer(BlockingQueue q) { queue = q; }
   public void run() {
     long sum = 0;
     try {
       while (true) { 
          Towar x = (Towar)queue.take();
          if (x == null) return;
          counter++;
          sum+=x.getWaga();
          if(counter%100==0){
                System.out.println("Sum of "+counter+" items");
          }
       }
     } catch (InterruptedException ex) { ... handle ...}
   }
 }

CountDownLatch 您可以通过多种方式做到这一点。一种方法是使用 CountDownLatch 等待提供的要创建的项目数,并为 Sum Thread 传递一个信号,说明创建已完成。 当 1 个线程正在添加对象而另一个线程正在使用增强的 for 循环时,列表​​将抛出并发修改。您可以通过使用简单的 for 循环或 while 循环等来解决这个问题。

I have written a Sample Program that can be used for your requirement. Go thru it 

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;

public class SynchronousListItems {

    public static void main(String[] args) {

        List<Item> items = new ArrayList<>();

        CountDownLatch creatorLatch = new CountDownLatch(1);
        CountDownLatch sumLatch = new CountDownLatch(1);

        int numberOfItemsToCreate = 100;

        Thread createrThread = new Thread(new Creator(items, creatorLatch, numberOfItemsToCreate));
        createrThread.setDaemon(true);

        Sum sumObj = new Sum(items, sumLatch);

        Thread sumThread = new Thread(sumObj);
        sumThread.setDaemon(true);

        createrThread.start();
        sumThread.start();

        try {
            creatorLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            sumObj.setStopSignal(true);
        }

        try {
            sumLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

}

class Creator implements Runnable {

    private List<Item> items;

    private CountDownLatch creatorLatch;

    private int numberOfItemsToCreate;

    public Creator(List<Item> items, CountDownLatch creatorLatch, int numberOfItemsToCreate) {
        this.items = items;
        this.creatorLatch = creatorLatch;
        this.numberOfItemsToCreate = numberOfItemsToCreate;
    }

    @Override
    public void run() {

        Random random = new Random(10L);

        while (numberOfItemsToCreate > 0) {
            int wage = random.nextInt();
            System.out.println(wage);
            items.add(new Item(wage));
            numberOfItemsToCreate--;
        }

        creatorLatch.countDown();
    }

}

class Item {

    private int wage;

    public Item(int wage) {
        this.wage = wage;
    }

    public int getWage() {
        return wage;
    }

}

class Sum implements Runnable {
    private boolean stopSignal;

    private List<Item> items;

    private int total;

    private int itemsCounter;

    private CountDownLatch sumLatch;

    public Sum(List<Item> items, CountDownLatch sumLatch) {
        this.items = items;
        this.sumLatch = sumLatch;
    }

    @Override
    public void run() {

        try {
            while (!stopSignal) {
                if (items != null && !items.isEmpty() && items.size() > itemsCounter) {
                    System.out.println("Itemes are not empty");
                    System.out.println("Itemes Counter " + itemsCounter);
                    while (itemsCounter < items.size()) {
                        Item item = items.get(itemsCounter);
                        System.out.println("Item Pulled");
                        total = total + item.getWage();
                        itemsCounter++;
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            System.out.println("Final Items Counter :" + itemsCounter);
            System.out.println("Total :" + total);
            sumLatch.countDown();
        }
    }

    public void setStopSignal(boolean stopSignal) {
        this.stopSignal = stopSignal;
    }
}