日韩成人免费在线_国产成人一二_精品国产免费人成电影在线观..._日本一区二区三区久久久久久久久不

當前位置:首頁 > 科技  > 軟件

這些Java并發容器,你都了解嗎?

來源: 責編: 時間:2023-12-08 09:15:56 252觀看
導讀前言在多線程環境下,數據的并發訪問和修改是無法避免的問題。為了解決這個問題,Java 提供了一系列并發容器,這些容器在內部已經處理了并發問題,使得我們可以在多線程環境下安全地訪問和修改數據。并發容器1.ConcurrentHas

前言

在多線程環境下,數據的并發訪問和修改是無法避免的問題。BaO28資訊網——每日最新資訊28at.com

為了解決這個問題,Java 提供了一系列并發容器,這些容器在內部已經處理了并發問題,使得我們可以在多線程環境下安全地訪問和修改數據。BaO28資訊網——每日最新資訊28at.com

BaO28資訊網——每日最新資訊28at.com

BaO28資訊網——每日最新資訊28at.com

并發容器

BaO28資訊網——每日最新資訊28at.com

1.ConcurrentHashMap 并發版 HashMap

最常見的并發容器之一,可以用作并發場景下的緩存。底層依然是哈希表,但在 JAVA 8 中有了不小的改變,而 JAVA 7 和 JAVA 8 都是用的比較多的版本,因此經常會將這兩個版本的實現方式做一些比較(比如面試中)。BaO28資訊網——每日最新資訊28at.com

一個比較大的差異就是,JAVA 7 中采用分段鎖來減少鎖的競爭,JAVA 8 中放棄了分段鎖,采用 CAS(一種樂觀鎖),同時為了防止哈希沖突嚴重時退化成鏈表(沖突時會在該位置生成一個鏈表,哈希值相同的對象就鏈在一起),會在鏈表長度達到閾值(8)后轉換成紅黑樹(比起鏈表,樹的查詢效率更穩定)。BaO28資訊網——每日最新資訊28at.com

BaO28資訊網——每日最新資訊28at.com

示例
import java.util.concurrent.*;public class ConcurrentHashMapExample {  public static void main(String[] args) {      // Creating a ConcurrentHashMap      ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>();      // Adding elements to the ConcurrentHashMap      map.put("Key1", "Value1");      map.put("Key2", "Value2");      map.put("Key3", "Value3");      // Printing the ConcurrentHashMap      System.out.println("ConcurrentHashMap: " + map);  }}

BaO28資訊網——每日最新資訊28at.com

2.CopyOnWriteArrayList 并發版 ArrayList

并發版 ArrayList,底層結構也是數組,和 ArrayList 不同之處在于:當新增和刪除元素時會創建一個新的數組,在新的數組中增加或者排除指定對象,最后用新增數組替換原來的數組。BaO28資訊網——每日最新資訊28at.com

CopyOnWriteArrayList 的主要特性是,每當列表修改時,例如添加或刪除元素,它都會創建列表的一個新副本。原始列表和新副本都可以進行并發讀取,這樣就可以在不鎖定整個列表的情況下進行并發讀取。這種方法在讀取操作遠多于寫入操作的場景中非常有用。BaO28資訊網——每日最新資訊28at.com

適用場景:由于讀操作不加鎖,寫(增、刪、改)操作加鎖,因此適用于讀多寫少的場景。BaO28資訊網——每日最新資訊28at.com

局限:由于讀的時候不會加鎖(讀的效率高,就和普通 ArrayList 一樣),讀取的當前副本,因此可能讀取到臟數據。如果介意,建議不用。BaO28資訊網——每日最新資訊28at.com

看看源碼感受下:BaO28資訊網——每日最新資訊28at.com

圖片圖片BaO28資訊網——每日最新資訊28at.com

BaO28資訊網——每日最新資訊28at.com

示例
import java.util.concurrent.*;public class CopyOnWriteArrayListExample {  public static void main(String[] args) {      // 創建一個 CopyOnWriteArrayList      CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<String>();      // 向 CopyOnWriteArrayList 添加元素      list.add("Element1");      list.add("Element2");      list.add("Element3");      // 打印 CopyOnWriteArrayList      System.out.println("CopyOnWriteArrayList: " + list);  }}

BaO28資訊網——每日最新資訊28at.com

3.CopyOnWriteArraySet 并發 Set

基于 CopyOnWriteArrayList 實現(內含一個 CopyOnWriteArrayList 成員變量),也就是說底層是一個數組,意味著每次 add 都要遍歷整個集合才能知道是否存在,不存在時需要插入(加鎖)。BaO28資訊網——每日最新資訊28at.com

CopyOnWriteArraySet 的工作原理與 CopyOnWriteArrayList 類似。每當發生修改操作(如添加或刪除元素)時,它都會創建集合的一個新副本。原始集合和新副本都可以進行并發讀取,這樣就可以在不鎖定整個集合的情況下進行并發讀取。這種方法在讀取操作遠多于寫入操作的場景中非常有用。BaO28資訊網——每日最新資訊28at.com

適用場景:在 CopyOnWriteArrayList 適用場景下加一個,集合別太大(全部遍歷傷不起)。BaO28資訊網——每日最新資訊28at.com

BaO28資訊網——每日最新資訊28at.com

示例
import java.util.concurrent.*;public class CopyOnWriteArraySetExample {  public static void main(String[] args) {      // 創建一個 CopyOnWriteArraySet      CopyOnWriteArraySet<String> set = new CopyOnWriteArraySet<String>();      // 向 CopyOnWriteArraySet 添加元素      set.add("Element1");      set.add("Element2");      set.add("Element3");      // 打印 CopyOnWriteArraySet      System.out.println("CopyOnWriteArraySet: " + set);  }}

BaO28資訊網——每日最新資訊28at.com

4.ConcurrentLinkedQueue 并發隊列 (基于鏈表)

基于鏈表實現的并發隊列,使用樂觀鎖 (CAS) 保證線程安全。因為數據結構是鏈表,所以理論上是沒有隊列大小限制的,也就是說添加數據一定能成功。BaO28資訊網——每日最新資訊28at.com

ConcurrentLinkedQueue 是 Java 并發包的一部分,它是基于鏈接節點的無界線程安全隊列。它按照 FIFO(先進先出)的原則對元素進行排序。BaO28資訊網——每日最新資訊28at.com

ConcurrentLinkedQueue 的主要優點是它允許完全并發的插入,并且使用了一種高效的“wait-free”算法。BaO28資訊網——每日最新資訊28at.com

BaO28資訊網——每日最新資訊28at.com

示例
import java.util.concurrent.*;public class ConcurrentLinkedQueueExample {  public static void main(String[] args) {      // 創建一個 ConcurrentLinkedQueue      ConcurrentLinkedQueue<String> queue = new ConcurrentLinkedQueue<String>();      // 向 ConcurrentLinkedQueue 添加元素      queue.add("Element1");      queue.add("Element2");      queue.add("Element3");      // 打印 ConcurrentLinkedQueue      System.out.println("ConcurrentLinkedQueue: " + queue);  }}

BaO28資訊網——每日最新資訊28at.com

5.ConcurrentLinkedDeque 并發隊列 (基于雙向鏈表)

基于雙向鏈表實現的并發隊列,可以分別對頭尾進行操作,因此除了先進先出 (FIFO),也可以先進后出(FILO),當然先進后出的話應該叫它棧了。BaO28資訊網——每日最新資訊28at.com

ConcurrentLinkedDeque 是 Java 并發包的一部分,它是一個基于鏈接節點的無界并發雙端隊列。在 ConcurrentLinkedDeque 中,添加、刪除等操作可以在隊列的兩端進行,使其具有更高的并發性。BaO28資訊網——每日最新資訊28at.com

BaO28資訊網——每日最新資訊28at.com

示例
import java.util.concurrent.*;public class ConcurrentLinkedDequeExample {  public static void main(String[] args) {      // 創建一個 ConcurrentLinkedDeque      ConcurrentLinkedDeque<String> deque = new ConcurrentLinkedDeque<String>();      // 向 ConcurrentLinkedDeque 添加元素      deque.add("Element1");      deque.addFirst("Element2");      deque.addLast("Element3");      // 打印 ConcurrentLinkedDeque      System.out.println("ConcurrentLinkedDeque: " + deque);  }}

BaO28資訊網——每日最新資訊28at.com

6.ConcurrentSkipListMap 基于跳表的并發 Map

ConcurrentSkipListMap 是 Java 并發包的一部分,它是一個線程安全的排序映射表。它使用跳表的數據結構來保證元素的有序性和并發性。BaO28資訊網——每日最新資訊28at.com

跳表是一種可以進行二分查找的有序鏈表。ConcurrentSkipListMap 提供了預期的平均 log(n) 時間成本來執行 containsKey,get,put 和 remove 操作,并且它的并發性通常優于基于樹的算法。BaO28資訊網——每日最新資訊28at.com

SkipList 即跳表,跳表是一種空間換時間的數據結構,通過冗余數據,將鏈表一層一層索引,達到類似二分查找的效果BaO28資訊網——每日最新資訊28at.com

圖片圖片BaO28資訊網——每日最新資訊28at.com

BaO28資訊網——每日最新資訊28at.com

示例
import java.util.concurrent.*;public class ConcurrentSkipListMapExample {  public static void main(String[] args) {      // 創建一個 ConcurrentSkipListMap      ConcurrentSkipListMap<String, String> map = new ConcurrentSkipListMap<String, String>();      // 向 ConcurrentSkipListMap 添加元素      map.put("Key1", "Value1");      map.put("Key2", "Value2");      map.put("Key3", "Value3");      // 打印 ConcurrentSkipListMap      System.out.println("ConcurrentSkipListMap: " + map);  }}

BaO28資訊網——每日最新資訊28at.com

7.ConcurrentSkipListSet 基于跳表的并發 Set

類似 HashSet 和 HashMap 的關系,ConcurrentSkipListSet 里面就是一個 ConcurrentSkipListMap,BaO28資訊網——每日最新資訊28at.com

ConcurrentSkipListSet 是 Java 并發包的一部分,它是一個線程安全的排序集合。它使用跳表的數據結構來保證元素的有序性和并發性。BaO28資訊網——每日最新資訊28at.com

跳表是一種可以進行二分查找的有序鏈表。ConcurrentSkipListSet 提供了預期的平均 log(n) 時間成本來執行 contains,add 和 remove 操作,并且它的并發性通常優于基于樹的算法。BaO28資訊網——每日最新資訊28at.com

BaO28資訊網——每日最新資訊28at.com

示例
import java.util.concurrent.*;public class ConcurrentSkipListSetExample {  public static void main(String[] args) {      // 創建一個 ConcurrentSkipListSet      ConcurrentSkipListSet<String> set = new ConcurrentSkipListSet<String>();      // 向 ConcurrentSkipListSet 添加元素      set.add("Element1");      set.add("Element2");      set.add("Element3");      // 打印 ConcurrentSkipListSet      System.out.println("ConcurrentSkipListSet: " + set);  }}

BaO28資訊網——每日最新資訊28at.com

8.ArrayBlockingQueue 阻塞隊列 (基于數組)

ArrayBlockingQueue 是 Java 并發包的一部分,它是一個基于數組的有界阻塞隊列。此隊列按 FIFO(先進先出)原則對元素進行排序。BaO28資訊網——每日最新資訊28at.com

ArrayBlockingQueue 在嘗試插入元素到已滿隊列或從空隊列中移除元素時,會導致線程阻塞,直到有空間或元素可用。BaO28資訊網——每日最新資訊28at.com

基于數組實現的可阻塞隊列,構造時必須制定數組大小,往里面放東西時如果數組滿了便會阻塞直到有位置(也支持直接返回和超時等待),通過一個鎖 ReentrantLock 保證線程安全。BaO28資訊網——每日最新資訊28at.com

圖片圖片BaO28資訊網——每日最新資訊28at.com

乍一看會有點疑惑,讀和寫都是同一個鎖,那要是空的時候正好一個讀線程來了不會一直阻塞嗎?BaO28資訊網——每日最新資訊28at.com

答案就在 notEmpty、notFull 里,這兩個出自 lock 的小東西讓鎖有了類似 synchronized + wait + notify 的功能。傳送門 → 終于搞懂了 sleep/wait/notify/notifyAllBaO28資訊網——每日最新資訊28at.com

BaO28資訊網——每日最新資訊28at.com

示例
import java.util.concurrent.*;public class ArrayBlockingQueueExample {  public static void main(String[] args) {      // 創建一個 ArrayBlockingQueue      ArrayBlockingQueue<String> queue = new ArrayBlockingQueue<String>(3);      // 向 ArrayBlockingQueue 添加元素      try {          queue.put("Element1");          queue.put("Element2");          queue.put("Element3");      } catch (InterruptedException e) {          e.printStackTrace();      }      // 打印 ArrayBlockingQueue      System.out.println("ArrayBlockingQueue: " + queue);  }}

BaO28資訊網——每日最新資訊28at.com

9.LinkedBlockingQueue 阻塞隊列 (基于鏈表)

LinkedBlockingQueue 是 Java 并發包的一部分,它是一個基于鏈表的可選有界阻塞隊列。此隊列按照 FIFO(先進先出)的原則對元素進行排序。BaO28資訊網——每日最新資訊28at.com

LinkedBlockingQueue 在嘗試插入元素到已滿隊列或從空隊列中移除元素時,會導致線程阻塞,直到有空間或元素可用。BaO28資訊網——每日最新資訊28at.com

基于鏈表實現的阻塞隊列,想比與不阻塞的 ConcurrentLinkedQueue,它多了一個容量限制,如果不設置默認為 int 最大值。BaO28資訊網——每日最新資訊28at.com

BaO28資訊網——每日最新資訊28at.com

示例
import java.util.concurrent.*;public class LinkedBlockingQueueExample {  public static void main(String[] args) {      // 創建一個 LinkedBlockingQueue      LinkedBlockingQueue<String> queue = new LinkedBlockingQueue<String>(3);      // 向 LinkedBlockingQueue 添加元素      try {          queue.put("Element1");          queue.put("Element2");          queue.put("Element3");      } catch (InterruptedException e) {          e.printStackTrace();      }      // 打印 LinkedBlockingQueue      System.out.println("LinkedBlockingQueue: " + queue);  }}

BaO28資訊網——每日最新資訊28at.com

10.LinkedBlockingDeque 阻塞隊列 (基于雙向鏈表)

LinkedBlockingDeque 是 Java 并發包的一部分,它是一個基于鏈表的可選有界阻塞雙端隊列。此隊列按照 FIFO(先進先出)的原則對元素進行排序。BaO28資訊網——每日最新資訊28at.com

LinkedBlockingDeque 在嘗試插入元素到已滿隊列或從空隊列中移除元素時,會導致線程阻塞,直到有空間或元素可用。雙端隊列的優勢在于可以從兩端插入或移除元素。BaO28資訊網——每日最新資訊28at.com

類似 LinkedBlockingQueue,但提供了雙向鏈表特有的操作。BaO28資訊網——每日最新資訊28at.com

BaO28資訊網——每日最新資訊28at.com

示例
import java.util.concurrent.*;public class LinkedBlockingDequeExample {  public static void main(String[] args) {      // 創建一個 LinkedBlockingDeque      LinkedBlockingDeque<String> deque = new LinkedBlockingDeque<String>(3);      // 向 LinkedBlockingDeque 添加元素      try {          deque.putFirst("Element1");          deque.putLast("Element2");          deque.putFirst("Element3");      } catch (InterruptedException e) {          e.printStackTrace();      }      // 打印 LinkedBlockingDeque      System.out.println("LinkedBlockingDeque: " + deque);  }}

BaO28資訊網——每日最新資訊28at.com

11.PriorityBlockingQueue 線程安全的優先隊列

PriorityBlockingQueue 是 Java 并發包的一部分,它是一個無界的并發隊列。它使用了和類 java.util.PriorityQueue 一樣的排序規則,并且能夠確保在并發環境下的線程安全。BaO28資訊網——每日最新資訊28at.com

PriorityBlockingQueue 中的元素按照自然順序或者由比較器提供的順序進行排序。隊列不允許使用 null 元素。BaO28資訊網——每日最新資訊28at.com

構造時可以傳入一個比較器,可以看做放進去的元素會被排序,然后讀取的時候按順序消費。某些低優先級的元素可能長期無法被消費,因為不斷有更高優先級的元素進來。BaO28資訊網——每日最新資訊28at.com

BaO28資訊網——每日最新資訊28at.com

示例
import java.util.concurrent.*;public class PriorityBlockingQueueExample {  public static void main(String[] args) {      // 創建一個 PriorityBlockingQueue      PriorityBlockingQueue<String> queue = new PriorityBlockingQueue<String>();      // 向 PriorityBlockingQueue 添加元素      queue.add("Element1");      queue.add("Element2");      queue.add("Element3");      // 打印 PriorityBlockingQueue      System.out.println("PriorityBlockingQueue: " + queue);  }}

BaO28資訊網——每日最新資訊28at.com

12.SynchronousQueue 數據同步交換的隊列

BaO28資訊網——每日最新資訊28at.com

SynchronousQueue 是 Java 并發包的一部分,它是一個不存儲元素的阻塞隊列。每一個 put 操作必須等待一個 take 操作,否則不能繼續添加元素,反之亦然。BaO28資訊網——每日最新資訊28at.com

這種特性使 SynchronousQueue 成為線程之間傳遞數據的好工具。它可以看作是一個傳球手,負責把生產者線程處理的數據直接傳遞給消費者線程。BaO28資訊網——每日最新資訊28at.com

一個虛假的隊列,因為它實際上沒有真正用于存儲元素的空間,每個插入操作都必須有對應的取出操作,沒取出時無法繼續放入。BaO28資訊網——每日最新資訊28at.com

BaO28資訊網——每日最新資訊28at.com

示例
import java.util.concurrent.SynchronousQueue;public class Main {     public static void main(String[] args) {      SynchronousQueue<Integer> queue = new SynchronousQueue<>();      new Thread(()->{          try{              for(int i=0;;i++){                  System.out.println("放入:" + i);                  queue.put(i);              }          }catch (InterruptedException e){              e.printStackTrace();          }      }).start();      new Thread(()->{          try{              while(true){                  System.out.println("取出:" + queue.take());                  Thread.sleep((long)(Math.random()*2000));              }          }catch (InterruptedException e){              e.printStackTrace();          }      }).start();  }}

運行結果:BaO28資訊網——每日最新資訊28at.com

取出:0放入:0取出:1放入:1放入:2取出:2取出:3放入:3取出:4放入:4......

可以看到,寫入的線程沒有任何 sleep,可以說是全力往隊列放東西,而讀取的線程又很不積極,讀一個又 sleep 一會。輸出的結果卻是讀寫操作成對出現。BaO28資訊網——每日最新資訊28at.com

JAVA 中一個使用場景就是 Executors.newCachedThreadPool(),創建一個緩存線程池。BaO28資訊網——每日最新資訊28at.com

圖片圖片BaO28資訊網——每日最新資訊28at.com

13.LinkedTransferQueue 基于鏈表的數據交換隊列

LinkedTransferQueue 是 Java 并發包的一部分,它是一個由鏈表結構組成的無界轉移阻塞隊列。隊列按照 FIFO(先進先出)的原則對元素進行排序。BaO28資訊網——每日最新資訊28at.com

LinkedTransferQueue 的一個特性是,它可以嘗試將元素直接轉移給消費者,如果沒有等待的消費者,元素就會被添加到隊列的尾部,等待消費者來獲取。BaO28資訊網——每日最新資訊28at.com

實現了接口 TransferQueue,通過 transfer 方法放入元素時,如果發現有線程在阻塞在取元素,會直接把這個元素給等待線程。如果沒有人等著消費,那么會把這個元素放到隊列尾部,并且此方法阻塞直到有人讀取這個元素。和 SynchronousQueue 有點像,但比它更強大。BaO28資訊網——每日最新資訊28at.com

BaO28資訊網——每日最新資訊28at.com

示例
import java.util.concurrent.*;public class LinkedTransferQueueExample {  public static void main(String[] args) {      // 創建一個 LinkedTransferQueue      LinkedTransferQueue<String> queue = new LinkedTransferQueue<String>();      // 啟動一個新線程來從 LinkedTransferQueue 取出元素      new Thread(() -> {          try {              System.out.println("Taken: " + queue.take());          } catch (InterruptedException e) {              e.printStackTrace();          }      }).start();      // 向 LinkedTransferQueue 添加一個元素      try {          queue.transfer("Element");      } catch (InterruptedException e) {          e.printStackTrace();      }  }}

BaO28資訊網——每日最新資訊28at.com

14.DelayQueue 延時隊列

DelayQueue 是 Java 并發包的一部分,它是一個無界阻塞隊列,只有在延遲期滿時才能從中提取元素。此隊列的頭部是延遲期滿后保存時間最長的元素。如果延遲都還沒有期滿,則隊列沒有頭部,并且 poll 將返回 null。BaO28資訊網——每日最新資訊28at.com

元素在 DelayQueue 中的順序是按照其到期時間的先后順序進行排序的,越早到期的元素越排在隊列前面。延遲隊列常用于實現定時任務功能。BaO28資訊網——每日最新資訊28at.com

可以使放入隊列的元素在指定的延時后才被消費者取出,元素需要實現 Delayed 接口。BaO28資訊網——每日最新資訊28at.com

BaO28資訊網——每日最新資訊28at.com

示例
import java.util.concurrent.*;public class DelayQueueExample {  public static void main(String[] args) {      // 創建一個 DelayQueue      DelayQueue<DelayedElement> queue = new DelayQueue<DelayedElement>();      // 向 DelayQueue 添加一個元素,延遲 3 秒      queue.put(new DelayedElement(3000, "Element"));      // 從 DelayQueue 獲取元素      try {          DelayedElement element = queue.take();          System.out.println("Taken: " + element);      } catch (InterruptedException e) {          e.printStackTrace();      }  }}class DelayedElement implements Delayed {  private long delayTime; // 延遲時間  private long expire; // 到期時間  private String element; // 元素數據  public DelayedElement(long delay, String element) {      this.delayTime = delay;      this.element = element;      this.expire = System.currentTimeMillis() + delay;  }  @Override  public long getDelay(TimeUnit unit) {      return unit.convert(expire - System.currentTimeMillis(), TimeUnit.MILLISECONDS);  }  @Override  public int compareTo(Delayed o) {      return (int) (this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS));  }  @Override  public String toString() {      return element;  }}

總結

BaO28資訊網——每日最新資訊28at.com

從上面的介紹總總結有以下幾種容器類BaO28資訊網——每日最新資訊28at.com

  1. ConcurrentHashMap:并發版 HashMap
  2. CopyOnWriteArrayList:并發版 ArrayList
  3. CopyOnWriteArraySet:并發 Set
  4. ConcurrentLinkedQueue:并發隊列 (基于鏈表)
  5. ConcurrentLinkedDeque:并發隊列 (基于雙向鏈表)
  6. ConcurrentSkipListMap:基于跳表的并發 Map
  7. ConcurrentSkipListSet:基于跳表的并發 Set
  8. ArrayBlockingQueue:阻塞隊列 (基于數組)
  9. LinkedBlockingQueue:阻塞隊列 (基于鏈表)
  10. LinkedBlockingDeque:阻塞隊列 (基于雙向鏈表)
  11. PriorityBlockingQueue:線程安全的優先隊列
  12. SynchronousQueue:讀寫成對的隊列
  13. LinkedTransferQueue:基于鏈表的數據交換隊列
  14. DelayQueue:延時隊列

Java 并發容器為處理多線程環境下的數據訪問和修改提供了強大的工具。BaO28資訊網——每日最新資訊28at.com

通過了解和學習這些并發容器,我們可以更好地理解并發編程,更有效地處理并發問題。BaO28資訊網——每日最新資訊28at.com

無論你是正在學習 Java,還是已經在使用 Java 進行開發,我都強烈建議你深入了解這些并發容器,它們將在你的并發編程之路上起到重要的作用。BaO28資訊網——每日最新資訊28at.com

本文鏈接:http://www.www897cc.com/showinfo-26-39538-0.html這些Java并發容器,你都了解嗎?

聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com

上一篇: 你應該知曉的 Rust Web 框架

下一篇: 前端技術探秘-Node.js的CommonJS規范實現原理

標簽:
  • 熱門焦點
Top 主站蜘蛛池模板: 镇赉县| 鸡西市| 新田县| 柳林县| 汉中市| 益阳市| 昌乐县| 莆田市| 高台县| 格尔木市| 永靖县| 林周县| 渑池县| 聊城市| 鄂尔多斯市| 深水埗区| 永城市| 吴忠市| 闸北区| 儋州市| 翼城县| 南康市| 平江县| 台南市| 壤塘县| 和硕县| 台湾省| 伊通| 阿图什市| 二连浩特市| 乌审旗| 海宁市| 玉环县| 麟游县| 嘉峪关市| 穆棱市| 藁城市| 皮山县| 灌阳县| 芮城县| 独山县|