【问题标题】:Synchronization of two method which work on ArrayList对 ArrayList 起作用的两种方法的同步
【发布时间】:2021-04-19 23:31:47
【问题描述】:

我有 Sum 类、Creator 类、Item 类和 MainCreator 创建随机项并将它们添加到 Item 类中的 ArrayList 中。 Sum 类读取项目并将所有的重量相加。在 Main 类中,我从多个线程 CreatorSum 开始。这两个类都实现了 Runnable 并覆盖了 run 方法。 200 个创建后的项目在控制台中打印。

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

求和类方法:

@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);
    }

创建者类方法:

@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");
    }

【问题讨论】:

    标签: java multithreading arraylist synchronization runnable


    【解决方案1】:

    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;
        }
    }
    

    【讨论】:

      【解决方案2】:

      BlockingQueue

      我建议使用BlockingQueue 接口的实现,而不是ArrayListBlockingQueuethread-safe

      引用 Javadoc:

      BlockingQueue 实现是线程安全的。所有排队方法都使用内部锁或其他形式的并发控制以原子方式实现其效果。然而,批量收集操作addAllcontainsAllretainAllremoveAll 不一定以原子方式执行,除非在实现中另外指定。因此,例如,addAll(c) 在仅添加 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 ...}
         }
       }
      

      【讨论】:

        猜你喜欢
        • 2015-07-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-02-25
        • 1970-01-01
        • 1970-01-01
        • 2013-10-31
        相关资源
        最近更新 更多