zoukankan      html  css  js  c++  java
  • ConcurrentHashMap

    在ConcurrentHashMap中,使用了分段锁机制,所以任意数量的读线程可以并发访问Map、读操作和写操作的线程可以并发访问Map、并且一定数量(默认是使用16个锁)的写线程也可以并发修改Map。ConcurrentHashMap提供的迭代器不会抛出ConcurrentModificationExeption,而且具有弱一致性,它可以容忍并发的修改。当创建迭代器时会遍历已有的元素,并可以(但是不保证)在迭代器被构造后将修改操作反映给容器。就是迭代器创建完成后,其他线程对map的修改,对遍历线程没有影响
    那么,当多个线程同时迭代一个ConcurrentHashMap的时候会发生什么呢?在遍历的时候更新又会发生什么呢?
    1,多个线程可以同时迭代ConcurrentHashMap;
    2,ConcurrentHashMap保证遍历的时候更新元素不会break(这正是并发容器的意义所在),但是不能保证数据的一致性,而迭代器保证的是:它反映的是创建迭代器时容器的状态。

    注意:
    从ConcurrentHashMap那里得到的iterator是为单线程设计的,即不可以传递它们,每一个线程都必须有自己的iterator。

    例子:

    (1)两个读线程和一个修改线程,每个线程各自拥有一个Iterator,并发访问ConcurrentHashMap。

    import java.util.Map;
    import java.util.Random;
    import java.util.UUID;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
     
    public class ConcurrentMapIteration
    {
      private final Map<String, String> map = new ConcurrentHashMap<String, String>();
     
      private final static int MAP_SIZE = 100000;
     
      public static void main(String[] args)
      {
        new ConcurrentMapIteration().run();
      }
     
      public ConcurrentMapIteration()
      {
        for (int i = 0; i < MAP_SIZE; i++)
        {
          map.put("key" + i, UUID.randomUUID().toString());
        }
      }
     
      private final ExecutorService executor = Executors.newCachedThreadPool();
     
      private final class Accessor implements Runnable
      {
        private final Map<String, String> map;
     
        public Accessor(Map<String, String> map)
        {
          this.map = map;
        }
     
        @Override
        public void run()
        {
          for (Map.Entry<String, String> entry : this.map.entrySet())
          {
            System.out.println(
                Thread.currentThread().getName() + " - [" + entry.getKey() + ", " + entry.getValue() + ']'
            );
          }
        }
      }
     
      private final class Mutator implements Runnable
      {
     
        private final Map<String, String> map;
        private final Random random = new Random();
     
        public Mutator(Map<String, String> map)
        {
          this.map = map;
        }
     
        @Override
        public void run()
        {
          for (int i = 0; i < 100; i++)
          {
            this.map.remove("key" + random.nextInt(MAP_SIZE));
            this.map.put("key" + random.nextInt(MAP_SIZE), UUID.randomUUID().toString());
            System.out.println(Thread.currentThread().getName() + ": " + i);
          }
        }
      }
     
      private void run()
      {
        Accessor a1 = new Accessor(this.map);
        Accessor a2 = new Accessor(this.map);
        Mutator m = new Mutator(this.map);
     
        executor.execute(a1);
        executor.execute(m);
        executor.execute(a2);
      }
    }
    结果:正常运行
    

      

    两个读线程共享一个Iterator
    
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Random;
    import java.util.UUID;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
     
    public class ConcurrentMapIteration
    {
      private final Map<String, String> map = new ConcurrentHashMap<String, String>();
      private final Iterator<Map.Entry<String, String>> iterator;
     
      private final static int MAP_SIZE = 100000;
     
      public static void main(String[] args)
      {
        new ConcurrentMapIteration().run();
      }
     
      public ConcurrentMapIteration()
      {
        for (int i = 0; i < MAP_SIZE; i++)
        {
          map.put("key" + i, UUID.randomUUID().toString());
        }
        this.iterator = this.map.entrySet().iterator();
      }
     
      private final ExecutorService executor = Executors.newCachedThreadPool();
     
      private final class Accessor implements Runnable
      {
        private final Iterator<Map.Entry<String, String>> iterator;
     
        public Accessor(Iterator<Map.Entry<String, String>> iterator)
        {
          this.iterator = iterator;
        }
     
        @Override
        public void run()
        {
          while(iterator.hasNext()) {
            Map.Entry<String, String> entry = iterator.next();
            try
            {
              String st = Thread.currentThread().getName() + " - [" + entry.getKey() + ", " + entry.getValue() + ']';
            } catch (Exception e)
            {
              e.printStackTrace();
            }
     
          }
        }
      }
     
      private final class Mutator implements Runnable
      {
     
        private final Map<String, String> map;
        private final Random random = new Random();
     
        public Mutator(Map<String, String> map)
        {
          this.map = map;
        }
     
        @Override
        public void run()
        {
          for (int i = 0; i < 100; i++)
          {
            this.map.remove("key" + random.nextInt(MAP_SIZE));
            this.map.put("key" + random.nextInt(MAP_SIZE), UUID.randomUUID().toString());
          }
        }
      }
     
      private void run()
      {
        Accessor a1 = new Accessor(this.iterator);
        Accessor a2 = new Accessor(this.iterator);
        Mutator m = new Mutator(this.map);
     
        executor.execute(a1);
        executor.execute(m);
        executor.execute(a2);
      }
    

      

    读线程和修改线程共享一个Iterator
    
    import java.util.Iterator;
    import java.util.Map;
    import java.util.Random;
    import java.util.UUID;
    import java.util.concurrent.ConcurrentHashMap;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
     
    public class ConcurrentMapIteration
    {
      private final Map<String, String> map = new ConcurrentHashMap<String, String>();
      private final Iterator<Map.Entry<String, String>> iterator;
     
      private final static int MAP_SIZE = 100000;
     
      public static void main(String[] args)
      {
        new ConcurrentMapIteration().run();
      }
     
      public ConcurrentMapIteration()
      {
        for (int i = 0; i < MAP_SIZE; i++)
        {
          map.put("key" + i, UUID.randomUUID().toString());
        }
        this.iterator = this.map.entrySet().iterator();
      }
     
      private final ExecutorService executor = Executors.newCachedThreadPool();
     
      private final class Accessor implements Runnable
      {
        private final Iterator<Map.Entry<String, String>> iterator;
     
        public Accessor(Iterator<Map.Entry<String, String>> iterator)
        {
          this.iterator = iterator;
        }
     
        @Override
        public void run()
        {
          while (iterator.hasNext())
          {
            Map.Entry<String, String> entry = iterator.next();
            try
            {
              String st =
                  Thread.currentThread().getName() + " - [" + entry.getKey() + ", " + entry.getValue() + ']';
            } catch (Exception e)
            {
              e.printStackTrace();
            }
     
          }
        }
      }
     
      private final class Mutator implements Runnable
      {
     
        private final Random random = new Random();
     
        private final Iterator<Map.Entry<String, String>> iterator;
     
        private final Map<String, String> map;
     
        public Mutator(Map<String, String> map, Iterator<Map.Entry<String, String>> iterator)
        {
          this.map = map;
          this.iterator = iterator;
        }
     
        @Override
        public void run()
        {
          while (iterator.hasNext())
          {
            try
            {
              iterator.remove();
              this.map.put("key" + random.nextInt(MAP_SIZE), UUID.randomUUID().toString());
            } catch (Exception ex)
            {
              ex.printStackTrace();
            }
          }
     
        }
      }
     
      private void run()
      {
        Accessor a1 = new Accessor(this.iterator);
        Accessor a2 = new Accessor(this.iterator);
        Mutator m = new Mutator(map, this.iterator);
     
        executor.execute(a1);
        executor.execute(m);
        executor.execute(a2);
      }

    结果:抛出java.lang.IllegalStateException异常。

  • 相关阅读:
    MySQL 中随机抽样:order by rand limit 的替代方案
    mysql下distinct和group by区别对比
    MVC中实现多按钮提交(转)
    js的逻辑 OR 运算符- ||
    js 实现键盘记录 兼容FireFox和IE
    jquery扩展
    sp_executesql的用法
    MVC中,视图的Layout使用
    MVC4的过滤器
    MVC中的Repository模式
  • 原文地址:https://www.cnblogs.com/wcss/p/13093575.html
Copyright © 2011-2022 走看看