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

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

JDK17 與 JDK11 特性差異淺談

來源: 責編: 時間:2024-01-26 09:01:14 208觀看
導讀1.1 switch 表達式語法變化在 JDK12 之前如果 switch 忘記寫 break 將導致貫穿,在 JDK12 中對 switch 的這一貫穿性做了改進。你只要將 case 后面的冒號改成箭頭,那么你即使不寫break也不會貫穿了。switch 可作為表達式

1.1 switch 表達式語法變化

  1. 在 JDK12 之前如果 switch 忘記寫 break 將導致貫穿,在 JDK12 中對 switch 的這一貫穿性做了改進。你只要將 case 后面的冒號改成箭頭,那么你即使不寫break也不會貫穿了。
  2. switch 可作為表達式,不再是單獨的語句。
  3. 當你把 switch 中的 case 后的冒號改為箭頭之后,此時 switch 就不會貫穿了,但在某些情況下,程序本來就希望貫穿比如我就希望兩個 case 共用一個執行體。JDK12 的 switch 中的 case 也支持多值匹配,這樣程序就變得更加簡潔了。
  4. JDK13 引入了一個新的 yield 語句來產生一個值,該值成為封閉的 switch 表達式的值。yield 和 return 的主要區別在于它們如何控制程序的流程。return 會結束當前的方法或函數,并將控制權返回給調用者。而 yield 則會暫時離開當前的 switch 表達式,將一個值返回給調用者,然后再回到 switch 表達式的地方繼續執行。
public class Demo{  public static void main(String[] args){    var score = 'C';    // 執行switch分支語句    String s = switch (score){      case 'A', 'B' -> "上等";      case 'C' -> "中等";      case 'D', 'E' -> "下等";       default -> {        if (score > 100) {          yield "數據不能超過100";        } else {          yield score + "此分數低于0分";        }      }    }   }}

1.2 微基準測試套件

JMH ,即 Java Microbenchmark Harness ,是專門用于代碼微基準測試的工具套件。K3c28資訊網——每日最新資訊28at.com

JMH 典型的應用場景

  1. 想定量地知道某個方法需要執行多長時間,以及執行時間和輸入參數的相關性。
  2. 一個接口有兩種不同實現,希望比較哪種實現性能更好。

JMH 使用案例

增加 JMH 的依賴

<properties>  <jmh.version>1.14.1</jmh.version></properties><dependencies>  <dependency>    <groupId>org.openjdk.jmh</groupId>    <artifactId>jmh-core</artifactId>    <version>${jmh.version}</version>  </dependency>  <dependency>    <groupId>org.openjdk.jmh</groupId>    <artifactId>jmh-generator-annprocess</artifactId>    <version>${jmh.version}</version>    <scope>provided</scope>  </dependency></dependencies>

代碼編寫

import org.openjdk.jmh.annotations.*;@State(Scope.Thread)public class MyBenchmark {  @Benchmark  @BenchmarkMode(Mode.All)  public void testMethod() {    try {      Thread.sleep(300);    } catch (InterruptedException e) {      e.printStackTrace();    }  }  @Benchmark  @BenchmarkMode(Mode.All)  public void testMethod2() {    try {      Thread.sleep(600);    } catch (InterruptedException e) {      e.printStackTrace();    }  }}
import org.openjdk.jmh.runner.Runner;import org.openjdk.jmh.runner.options.Options;import org.openjdk.jmh.runner.options.OptionsBuilder;public class BenchmarkRunner {  public static void main(String[] args) throws Exception {    Options opt = new OptionsBuilder()          .include(MyBenchmark.class.getSimpleName())          .forks(1)          .warmupIterations(5)          .measurementIterations(5)          .build();    new Runner(opt).run();  }}//以下這些方法都是JMH的一部分,可以在任何版本的JMH中使用。//include(SimpleBenchmark.class.getSimpleName()) :這個方法表示你想要運行哪個類的基準測試。//exclude("xxx") :這個方法表示你想要在基準測試中排除哪個方法。//forks(1) :這個方法表示你想要進行多少輪的基準測試。每一輪測試都會在一個新的 JVM 進程中進行,以確保每輪測試的環境是獨立的。//warmupIterations(5) :這個方法表示你想要進行多少次預熱迭代。預熱迭代是為了讓 JVM 達到穩定狀態,預熱迭代的結果不會被計入最終的基準測試結果。//measurementIterations(5) :這個方法表示你想要進行多少次正式的基準測試迭代,這些迭代的結果會被用來計算基準測試的最終結果。

結果輸出(只截取了一部分)

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

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

相關注解

@BenchmarkMode

對應 Mode 選項,可用于類或者方法上,需要注意的是,這個注解的 value 是一個數組,可以把幾種 Mode 集合在一起執行,還可以設置為 Mode.All ,即全部執行一遍。K3c28資訊網——每日最新資訊28at.com

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

  • 吞吐量 (thrpt) :單位時間內完成的操作次數,也可以理解為每秒能處理的事務數。
  • 平均時間 (avgt) :每次操作所需的平均時間。
  • 樣本時間 (sample) :隨機取樣,最后輸出取樣結果的分布,例如“99%的調用在xxx毫秒以內,99.99%的調用在xxx毫秒以內”。
  • 單次啟動時間 (ss) :SingleShotTime ,度量一次操作的運行時間,即每次迭代前都會重新初始化狀態。
@State

類注解,JMH 測試類必須使用 @State 注解,State 定義了一個類實例的生命周期,可以類比 SpringBean 的 Scope 。由于 JMH 允許多線程同時執行測試,不同的選項含義如下:K3c28資訊網——每日最新資訊28at.com

Scope.Thread :默認的 State ,每個測試線程分配一個實例。K3c28資訊網——每日最新資訊28at.com

Scope.Benchmark :所有測試線程共享一個實例,用于測試有狀態實例在多線程共享下的性能。K3c28資訊網——每日最新資訊28at.com

Scope.Group :每個線程組共享一個實例。K3c28資訊網——每日最新資訊28at.com

如果你想測試一個對象在多線程環境下的行為,你可以選擇 Scope.Benchmark 。如果你想要每個線程都有自己的狀態,你可以選擇 Scope.Thread 。如果你想要在同一線程組內的所有線程共享狀態,你可以選擇 Scope.Group 。K3c28資訊網——每日最新資訊28at.com

@OutputTimeUnit

benchmark 結果所使用的時間單位,可用于類或者方法注解,使用 java.util.concurrent.TimeUnit 中的標準時間單位。K3c28資訊網——每日最新資訊28at.com

@Benchmark

方法注解,表示該方法是需要進行 benchmark 的對象。K3c28資訊網——每日最新資訊28at.com

1.3 生成類數據共享特性優化

背景:在同一個物理機上啟動多個 JVM 時,如果每個虛擬機都單獨裝載自己需要的所有類,啟動成本和內存占用是比較高的。所以引入了類數據共享機制 ( Class Data Sharing ,簡稱 CDS ) 的概念,通過把一些核心類在每個 JVM 間共享,每個 JVM 只需要裝載自己的應用類即可。K3c28資訊網——每日最新資訊28at.com

JDK12 之前想要利用 CDS 的用戶,必須 -Xshare:dump 作為額外的步驟來運行。K3c28資訊網——每日最新資訊28at.com

JDK12 針對 64 位平臺使其默認生成類數據共享 ( CDS ) 歸檔。K3c28資訊網——每日最新資訊28at.com

好處:JVM啟動時間減少了。因為核心類是共享的,所以 JVM 的內存占用也減少了。K3c28資訊網——每日最新資訊28at.com

JDK13 則支持在應用運行之后進行動態歸檔。需要使用 -XX:ArchiveClassesAtExit=filename.jsa 選項來指定一個文件,JVM 會在退出時將應用程序類和標準庫類的元數據寫入這個文件。然后,在下一次啟動 JVM 時,你可以使用 -XX:SharedArchiveFile=filename.jsa 選項來指定剛才創建的文件。K3c28資訊網——每日最新資訊28at.com

好處:這個特性允許 JVM 在運行時捕獲類的元數據,然后在下一次 JVM 啟動時重用這些元數據,從而提高啟動速度和減少內存占用。K3c28資訊網——每日最新資訊28at.com

1.4 G1 垃圾收集器和 ZGC 功能增強

  1. 在 JDK12 之前,一旦開始執行垃圾收集,即使可能會超過 -XX:MaxGCPauseMillis 參數設定的值,也不會停止。JDK12 中,如果 G1 垃圾收集器有可能超過預期的暫停時間,則可以終止。G1 垃圾收集器發現反復標記過多的區域后,G1 就會切換到更增量的一種 Mix GC 。它將待回收的集合分為兩個部分:強制回收和可選回收。強制回收的部分是 G1 無法增量回收的部分(比如年輕代)也可以包含能增量回收的部分(比如老年代)來提升性能,它占待回收集合的 80% 。當 G1 回收完強制回收部分后,如果還有多余的時間,將會更細粒度的處理可選回收部分,每次只會處理一個區域,避免超過用戶指定的時間。在處理完一個區域后,G1 會根據剩余的時間來決定是否繼續處理剩余的可選部分。
  2. JDK12 中,如果應用程序活動非常低,G1 可以使其能夠在空閑時自動將 Java 堆內存返還給操作系統。
  3. JDK13 中,ZGC 也能夠主動釋放未使用內存給操作系統,但可以通過 -XX : -ZUncommit 參數來顯示關閉此功能。ZGC 支持最大堆大小為 16TB ,可以滿足大多數大型服務器的需求。
  4. ZGC 是在 JDK11 中引入的垃圾回收器,但一直都是實驗版本,在 JDK15 中正式上線,如果你的應用程序需要處理非常大的堆或者更低的暫停時間,那么 ZGC 可能是一個更好的選擇。如果你對兼容性和穩定性有更高的要求,因為 G1 經過長時間的驗證和優化,可能 G1 更適合。

1.5 ShenandoahGC

添加一個名為 Shenandoah 的新垃圾收集算法,通過與正在運行的 Java 線程同時進行疏散工作來減少 GC 暫停時間,最終目標旨在針對 JVM 上的內存收回實現低停頓的需求。K3c28資訊網——每日最新資訊28at.com

Shenandoah 是以實驗特性在 JDK12 中引入的。在 JDK15 中正式上線。K3c28資訊網——每日最新資訊28at.com

使用 Shenandoah 的暫停時間與堆大小無關,這意味著無論堆是 200MB 還是 200GB ,都將具有相同的一致暫停時間。與 ZGC 類似,Shenandoah GC 主要目標是 99.9% 的暫停小于 10ms ,暫停與堆大小無關等。K3c28資訊網——每日最新資訊28at.com

ZGC 和 ShenandoahGC 的一些主要區別:K3c28資訊網——每日最新資訊28at.com

  1. 設計目標:ZGC 和 ShenandoahGC 都是為了實現低延遲的垃圾收集而設計的。
  2. 并發回收:ShenandoahGC 實現了并發回收,這意味著它可以在應用線程運行的同時進行垃圾收集,從而減少了垃圾收集對應用性能的影響。
  3. 內存管理:ShenandoahGC 使用名為“連接矩陣”的全局數據結構來記錄跨 Region 的引用關系,降低了處理跨代指針時的記憶集維護消耗。而 ZGC 的 Region 可以動態創建和銷毀,容量也可以動態調整。
  4. 開發者:Shenandoah 由 RedHat 開發,而 ZGC 由 Oracle 開發。

使用方法:要啟用/使用 Shenandoah GC,需要以下 JVM 選項: -XX:+UnlockExperimentalVMOptions -XX:+UseShenandoahGC。作為實驗性功能,Shenandoah 構建系統會自動禁用不受支持的配置。K3c28資訊網——每日最新資訊28at.com

1.6 String 新增方法

  1. transform(Function):對字符串進行處理后返回。
var rs = "test".transform(s -> s + "Java").transform(s -> s.toUpperCase()); // TESTJAVA
  1. indent:該方法允許我們調整String實例的縮進。
String result = "Java/njava/ntest".indent(3);/*結果會縮進三格   Java   java   test*/

1.7 Files 新增 mismatch 方法

返回內容第一次不匹配的字符位置索引。K3c28資訊網——每日最新資訊28at.com

System.out.println(Files.mismatch(Path.of("a.txt"),Path.of("b.txt")));

1.8 核心庫 java.text 支持壓縮數字格式

NumberFormat 添加了對 ”緊湊形式格式化數字“ 的支持。K3c28資訊網——每日最新資訊28at.com

”緊湊數字格式“是指以簡短或人類可讀形式表示的數字。K3c28資訊網——每日最新資訊28at.com

例如,在 en_US 語言環境中,1000 可以格式化為 “ 1K ”,1000000 可以格式化為 “ 1M ”,具體取決于指定的樣式 NumberFormat.Style 。緊湊數字格式由 LDML 的 Compact Number 格式規范定義。要獲取實例,請使用 NumberFormat 緊湊數字格式所給出的工廠方法之一。K3c28資訊網——每日最新資訊28at.com

NumberFormat fmt = NumberFormat.getCompactNumberInstance(Locale.US, NumberFormat.Style.SHORT);String result = fmt.format(1000);//1Kvar cnf = NumberFormat.getCompactNumberInstance(Locale.CHINA,NumberFormat.Style.SHORT);System.out.println(cnf.format(5_0000));//"5萬"System.out.println(cnf.format(7_9200));//"7.9萬"System.out.println(cnf.format(8_000_000));//"800萬"System.out.println(cnf.format(9L << 30));//"96億"System.out.println(cnf.format(6L << 50));//"5637142兆"System.out.println(cnf.format(6L << 60));//"6917529京"

1.9 JDK17 支持到 Unicode13

JDK12 支持 Unicode11.0K3c28資訊網——每日最新資訊28at.com

JDK13 支持 Unicode12.1K3c28資訊網——每日最新資訊28at.com

從 JDK14 到 JDK17 均是支持 Unicode13.0K3c28資訊網——每日最新資訊28at.com

1.10 NullPointerExceptions 升級

JDK14 之前,從報錯中我們只能得到錯誤出現的行數,但在 JDK14 之后,會清晰的告訴你哪個對象空指針了。K3c28資訊網——每日最新資訊28at.com

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "String.charAt(int)" because "str" is nullat com.qf.jdk14.Test.main(Test.java:11)

1.11 文本塊特性

背景:在 Java 中,在字符串文字中嵌入 HTML ,XML ,SQL 或 JSON 片段通常需要先進行轉義和串聯的大量編輯,然后才能編譯包含該片段的代碼。該代碼段通常難以閱讀且難以維護。K3c28資訊網——每日最新資訊28at.com

Java 的文本塊特性是在 JDK15 中正式實現的。這個特性首先在 JDK13 中以預覽版的形式發布,然后在 JDK14 中改進并再次以預覽版的形式發布。這一特性提高了 Java 程序書寫大段字符串文本的可讀性和方便性。K3c28資訊網——每日最新資訊28at.com

文本塊的開頭定界符是由三個雙引號 """ 開始,從新的一行開始字符串的內容,以 """ 結束。如果結束的 """ 另起一行時,字符串內容最后會留有一新行。K3c28資訊網——每日最新資訊28at.com

使用案例

String query = "SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`/n" +               "WHERE `CITY` = 'INDIANAPOLIS'/n" +               "ORDER BY `ID`, `LAST_NAME`;";//使用文本塊語法String query = """               SELECT `EMP_ID`, `LAST_NAME` FROM `EMPLOYEE_TB`               WHERE `CITY` = 'INDIANAPOLIS'               ORDER BY `EMP_ID`, `LAST_NAME`;""";
String html = "<html>/n" +              "    <body>/n" +              "        <p>Hello, world</p>/n" +              "    </body>/n" +              "</html>/n";//使用文本塊語法String html = """              <html>                  <body>                      <p>Hello, world</p>                  </body>              </html>              """;

縮進示例

Java 編譯器會自動刪除不需要的縮進:K3c28資訊網——每日最新資訊28at.com

  • 每行結尾的空格都會刪除。
  • 每行開始的共有的空格會自動刪除。
  • 只保留相對縮進。
  • 新行 """ 結束時,將 """ 向左調整,則可以給所有行前加相應數量的空格。將 """ 向右調整,沒有作用。
System.out.println("""        Hello,          multiline        text blocks!    """);// 結果// >     Hello,// >       multiline// >     text blocks!

1.12 重新實現舊版 Socket API

背景:現在已有的 java.net.Socket 和 java.net.ServerSocket 以及它們的實現類,都可以回溯到 JDK1.0 時代了。原始 socket 的維護和調試都很痛苦。實現類還使用了線程棧作為 I/O 的緩沖,導致在某些情況下還需要增加線程棧的大小。該實現還存在幾個并發問題,需要徹底解決。在未來的網絡世界,要快速響應,不能阻塞本地方法線程,當前的實現不適合使用了。K3c28資訊網——每日最新資訊28at.com

JDK13 全新實現的 NioSocketImpl 來替換 JDK1 的 SocketImpl 和 PlainSocketImpl。K3c28資訊網——每日最新資訊28at.com

  • 它便于維護和調試,與 NewI/O (NIO) 使用相同的 JDK 內部結構,因此不需要使用系統本地代碼。
  • 它與現有的緩沖區緩存機制集成在一起,這樣就不需要為 I/O 使用線程棧。
  • 它使用 java.util.concurrent 鎖,而不是 synchronized 同步方法,增強了并發能力。
  • 新的實現是 JDK13 中的默認實現,但是舊的實現還沒有刪除,可以通過設置參數 -Djdk.net.usePlainSocketImpl=true 來切換到舊版本。

1.13 Hidden Classes

通常我們在使用大型的框架或者 lambda 表達式的時候,會動態生成很多類。但是不幸的是標準的定義類的API:ClassLoader::defineClass 和 Lookup::defineClass 不能夠區分出這些類是動態生成(運行時生成)的還是靜態生成(編譯生成)的。K3c28資訊網——每日最新資訊28at.com

一般來說動態生成的類生命周期更短,并且其可?性要更低。但是現有的 JDK 并沒有這個功能。K3c28資訊網——每日最新資訊28at.com

所有有了 HiddenClasses 的提案,通過 HiddenClasses ,不管是 JDK 還是 JDK 外部的框架,在生成動態類的時候都可以定義為 HiddenClasses,這樣可以更加有效的控制這些動態生成類的生命周期和可?性。K3c28資訊網——每日最新資訊28at.com

1.14 instanceof 關鍵詞

instanceof關鍵詞主要用來判斷某個對象是不是某個類的實例。K3c28資訊網——每日最新資訊28at.com

比如,有時候我們要處理一個類似這樣的數據集:K3c28資訊網——每日最新資訊28at.com

Map<String, Object> data = new HashMap<>();data.put("test", "111");data.put("test2", 222);

JDK16 之前需要先判斷獲取的 value 是否是 String ,再做強制類型轉換:K3c28資訊網——每日最新資訊28at.com

Object value = data.get("test");if (value instanceof String){  String s = (String) value;  System.out.println(s.substring(1));}

在 JDK16 的增強之后,對于 instanceof 的判斷以及類型轉換可以合二為一了:K3c28資訊網——每日最新資訊28at.com

Object value = data.get("test");if (value instanceof String s){ System.out.println(s.substring(1));}

1.15 檔案類

Records 的目標是擴展 Java 語言語法,Records 為聲明類提供了一種緊湊的語法,通過對類做這樣的聲明,編譯器可以通過自動創建所有方法并讓所有字段參與 hashCode() 等方法。其目的是為了充當不可變數據的透明載體的類。K3c28資訊網——每日最新資訊28at.com

舊方法定義實體類,代碼如下:K3c28資訊網——每日最新資訊28at.com

public final class User {  final String name;  final int age;  public User(String name, int age) {    this.name = name;    this.age = age;  }  @Override  public String toString() {    return "User{" +          "name='" + name + '/'' +          ", age=" + age +          '}';  }  @Override  public boolean equals(Object o) {    if (this == o) return true;    if (o == null || getClass() != o.getClass()) return false;    User user = (User) o;    return age == user.age && Objects.equals(name, user.name);  }  @Override  public int hashCode() {   return Objects.hash(name, age);  }}

通過 Record 類方式,一句話就可以實現以上功能,代碼如下:K3c28資訊網——每日最新資訊28at.com

public record User(String username, String password) {}

在 JDK16 之前的版本中,我們不能在類名后面直接寫參數來定義類的狀態。這是 JDK16 引入 record 類的一個新特性。K3c28資訊網——每日最新資訊28at.com

調用 Record 類方式,如下:K3c28資訊網——每日最新資訊28at.com

public class App {  public static void main(String[] args) {    User user = new User("user", "123456");    System.out.println(user.username());  }}

注意事項:K3c28資訊網——每日最新資訊28at.com

  • record 類不允許使用 abstract 關鍵字定義為抽象
  • 所有成員變量均為 final 修飾,不允許再次賦值
  • 允許出現靜態變量/實例方法/靜態方法
  • 允許出現其他構造方法,但必須調用 record 構造方法
  • Record 不允許 extends 繼承其他類

1.16 密封類

在 JDK15 中,Java 提出了密封類( Sealed Classes )的概念,在 JDK17 中被正式確認。密封類允許類和接口定義其允許的子類型。因此,如果一個類沒有顯式地使用 sealed 、non-sealed 或 final 關鍵字,那么它的默認權限就是 non-sealed 。K3c28資訊網——每日最新資訊28at.com

以下是一個密封類的代碼示例:K3c28資訊網——每日最新資訊28at.com

sealed class Human permits Kyrie, LeBron, George {  public void printName() {   System.out.println("Default");  }}non-sealed class Kyrie extends Human {  public void printName() {   System.out.println("Bob");  }}sealed class LeBron extends Human {  public void printName() {   System.out.println("Mike");  }}final class George extends Human {  public void printName() {   System.out.println("Yannick");  }}

在這個例子中,Human 是一個密封類,它只允許 Kyrie,LeBron 和 George 這三個類繼承。這樣,我們就可以更精確地控制哪些類可以繼承 Human 類,從而提高代碼的安全性和可讀性。K3c28資訊網——每日最新資訊28at.com

1.17 統一日志異步刷新

在 JDK17 中,引入了一項新特性:統一日志異步刷新。K3c28資訊網——每日最新資訊28at.com

先將日志寫入緩存,然后再異步地刷新到日志文件,這樣寫日志的操作就不會阻塞執行業務邏輯的線程,從而提高了程序的運行效率。這個特性對于需要大量日志輸出,并且對性能有較高要求的應用來說,是一個非常實用的改進。可以通過傳遞命令行選項 -Xlog:async 來開啟此功能。K3c28資訊網——每日最新資訊28at.com

總結

從 JDK11 到 JDK17 ,Java 的發展經歷了一系列重要的里程碑。其中最重要的是 JDK17 的發布,這是一個長期支持(LTS)版本,它將獲得長期的更新和支持,有助于保持程序的穩定性和可靠性。此外,Java 的性能也有了顯著的提升。這些進步都反映了 Java 在持續改進和適應現代編程需求方面的承諾。K3c28資訊網——每日最新資訊28at.com

參考文檔

  1. https://openjdk.org/projects/jdk/
  2. JDK12: JDK12新功能深度解析_jdk12新特性-CSDN博客
  3. switch statement - What does the new keyword "yield" mean in Java 13? - Stack Overflow
  4. New Features in Java 13 | Baeldung
  5. Java 11 and 12 - New Features (packtpub.com)
  6. Java 16 and IntelliJ IDEA | The IntelliJ IDEA Blog (jetbrains.com)
  7. Sealed Class in Java - GeeksforGeeks

本文鏈接:http://www.www897cc.com/showinfo-26-68322-0.htmlJDK17 與 JDK11 特性差異淺談

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

上一篇: 12個強大的 JavaScript 動畫庫,可幫助你提升用戶體驗

下一篇: 基于Redisson的RAtomicLong實現全局唯一工單號生成器

標簽:
  • 熱門焦點
Top 主站蜘蛛池模板: 桐庐县| 唐河县| 大田县| 荃湾区| 贵德县| 武清区| 钟祥市| 理塘县| 延边| 永善县| 乐都县| 丰城市| 泸定县| 台中县| 浦北县| 容城县| 靖远县| 阜新市| 日土县| 丰镇市| 岐山县| 大埔县| 通辽市| 太白县| 大厂| 榆中县| 普宁市| 环江| 金昌市| 南汇区| 连江县| 石屏县| 泸西县| 册亨县| 河东区| 丰台区| 五常市| 莒南县| 六盘水市| 来凤县| 池州市|