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

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

深入理解與應用多線程技術

來源: 責編: 時間:2024-01-09 08:52:02 237觀看
導讀為什么要使用多線程提高響應速度:對于耗時操作,使用線程可以避免阻塞主線程,提高應用程序的響應速度。實現并行操作:在多CPU系統中,使用線程可以并行處理任務,提高CPU利用率。改善程序結構:將一個既長又復雜的進程分為多個線

為什么要使用多線程

  1. 提高響應速度:對于耗時操作,使用線程可以避免阻塞主線程,提高應用程序的響應速度。
  2. 實現并行操作:在多CPU系統中,使用線程可以并行處理任務,提高CPU利用率。
  3. 改善程序結構:將一個既長又復雜的進程分為多個線程,可以使其成為幾個獨立或半獨立的運行部分,這樣有利于程序的修改和理解。
  4. 方便的通信機制:線程間可以通過共享內存等方式進行通信,比進程間通信更方便、高效。

創建線程有幾種方式?

創建線程有四種方式:xHe28資訊網——每日最新資訊28at.com

  1. 通過繼承Thread類來創建線程。
  2. 通過實現Runnable接口來創建線程。
  3. 通過實現Callable接口來創建線程。
  4. 使用Executor框架來創建線程池。

簡單實現

public class ThreadTest {    public static void main(String[] args) {        Thread thread = new MyThread();        thread.start();    }}class MyThread extends Thread {    @Override    public void run() {        System.out.println("關注公眾號:一安未來");    }}
public class ThreadTest {    public static void main(String[] args) {        MyRunnable myRunnable = new MyRunnable();        Thread thread = new Thread(myRunnable);        thread.start();    }}class MyRunnable implements Runnable {    @Override    public void run() {        System.out.println("關注公眾號:一安未來");    }}
public class ThreadTest {    public static void main(String[] args) throws ExecutionException, InterruptedException {        MyThreadCallable mc = new MyThreadCallable();        FutureTask<Integer> ft = new FutureTask<>(mc);        Thread thread = new Thread(ft);        thread.start();        System.out.println(ft.get());    }}class MyThreadCallable implements Callable {    @Override    public String call()throws Exception {        return "關注公眾號:一安未來";    }}
public class ThreadTest {    public static void main(String[] args) throws Exception {        ThreadPoolExecutor executorOne = new ThreadPoolExecutor(5, 5, 1,                TimeUnit.MINUTES, new ArrayBlockingQueue<Runnable>(20), new CustomizableThreadFactory("Yian-Thread-pool"));        executorOne.execute(() -> {            System.out.println("關注公眾號:一安未來");        });        //關閉線程池        executorOne.shutdown();    }}

線程和進程的區別

線程和進程是操作系統中重要的概念,都是操作系統資源分配的基本單位,但它們有一些關鍵的區別。xHe28資訊網——每日最新資訊28at.com

  1. 地址空間和資源擁有:進程是執行中的一個程序,具有自己的地址空間和文件描述符等資源。線程是在進程中執行的一個單獨的執行路徑,共享進程的地址空間和資源。
  2. 開銷:創建和銷毀一個進程需要保存寄存器、棧信息以及進行資源分配和回收等操作,開銷較大。而線程的創建和銷毀只需保存寄存器和棧信息,開銷較小。
  3. 通信切換:進程之間必須通過IPC(進程間通信)進行通信,切換開銷相對較大。線程之間可以直接共享進程的地址空間和資源,切換開銷相對較小。
  4. 并發性:進程是獨立的執行單元,具有自己的調度算法,在并發條件下更加穩定可靠。而線程共享進程的資源,線程之間的調度和同步比較復雜,對并發條件的處理需要更多的注意。
  5. 一對多的關系:一個線程只能屬于一個進程,而一個進程可以擁有多個線程。

Runnable和 Callable有什么區別

  • Runnable接口只有一個需要實現的方法,即run()。當你啟動一個線程時,這個run()方法就會被執行。Runnable的主要問題是它不支持返回結果
  • Callable可以返回結果,也可以拋出異常。它有一個call()方法,當調用這個方法時,這個方法就會被執行。

volatile作用,原理

主要用于聲明變量,以指示該變量可能會被多個線程同時訪問,從而防止編譯器進行一些優化,確保線程之間能夠正確地讀寫共享變量。volatile 提供了一種輕量級的同步機制,但它并不能替代 synchronized,因為它無法解決復合操作的原子性問題。xHe28資訊網——每日最新資訊28at.com

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

作用:xHe28資訊網——每日最新資訊28at.com

  • 可見性: 當一個線程修改了一個被 volatile 修飾的變量的值,其他線程能夠立即看到這個修改,即保證了變量的可見性。
  • 禁止指令重排序: volatile 修飾的變量的讀寫操作會禁止指令重排序,確保變量的寫操作不會被重排序到其它操作之前。

原理:xHe28資訊網——每日最新資訊28at.com

volatile 的實現原理涉及到 CPU 的緩存一致性和內存屏障(Memory Barrier)的概念。xHe28資訊網——每日最新資訊28at.com

  • 內存可見性: 當一個線程寫入一個 volatile 變量時,會強制將該線程對應的本地內存中的值刷新到主內存中,從而保證了其他線程能夠看到最新的值。同樣,當一個線程讀取一個 volatile 變量時,會強制從主內存中讀取最新的值到本地內存中。
  • 禁止指令重排序: volatile 修飾的變量的讀寫操作會在其前后插入內存屏障,防止在其前后的指令被重排序。

synchronized 的實現原理以及鎖優化

如果synchronized作用于代碼塊,反編譯可以看到兩個指令:monitorenter、monitorexit,JVM使用monitorenter和monitorexit兩個指令實現同步;如果作用synchronized作用于方法,反編譯可以看到ACCSYNCHRONIZED標記,JVM通過在方法訪問標識符(flags)中加入ACCSYNCHRONIZED來實現同步功能。xHe28資訊網——每日最新資訊28at.com

  • 同步代碼塊,當線程執行到monitorenter的時候要先獲得monitor鎖,才能執行后面的方法。當線程執行到monitorexit的時候則要釋放鎖。
  • 同步方法,當線程執行有ACCSYNCHRONI標志的方法,需要獲得monitor鎖。每個對象都與一個monitor相關聯,線程可以占有或者釋放monitor。

monitor監視器

操作系統的管程(monitors)是概念原理,ObjectMonitor是它的原理實現。xHe28資訊網——每日最新資訊28at.com

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

在Java虛擬機(HotSpot)中,Monitor(管程)是由ObjectMonitor實現的,其主要數據結構如下:xHe28資訊網——每日最新資訊28at.com

ObjectMonitor() {    _header       = NULL;    _count        = 0; // 記錄個數    _waiters      = 0,    _recursions   = 0;    _object       = NULL;    _owner        = NULL;    _WaitSet      = NULL;  // 處于wait狀態的線程,會被加入到_WaitSet    _WaitSetLock  = 0 ;    _Responsible  = NULL ;    _succ         = NULL ;    _cxq          = NULL ;    FreeNext      = NULL ;    _EntryList    = NULL ;  // 處于等待鎖block狀態的線程,會被加入到該列表    _SpinFreq     = 0 ;    _SpinClock    = 0 ;    OwnerIsThread = 0 ;  }

Java Monitor 的工作機理

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

  • 要獲取monitor的線程,首先會進入EntryList隊列。
  • 當某個線程獲取到對象的monitor后,進入Owner區域,設置為當前線程,同時計數器count加1。
  • 如果線程調用了wait()方法,則會進入WaitSet隊列阻塞等待。它會釋放monitor鎖,即將owner賦值為null,count自減1。
  • 如果其他線程調用 notify()/notifyAll() ,會喚醒WaitSet中的某個或全部線程,該線程再次嘗試獲取monitor鎖,成功即進入Owner區域。
  • 同步方法執行完畢了,線程退出臨界區,會將monitor的owner設為null,并釋放監視鎖

對象與monitor關聯

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

  • 在HotSpot虛擬機中,對象在內存中存儲的布局可以分為3塊區域:對象頭(Header),實例數據(Instance Data)和對象填充(Padding)。
  • 對象頭主要包括兩部分數據:Mark Word(標記字段)、Class Pointer(類型指針)。

Mark Word 是用于存儲對象自身的運行時數據,如哈希碼(HashCode)、GC分代年齡、鎖狀態標志、線程持有的鎖、偏向線程 ID、偏向時間戳等。xHe28資訊網——每日最新資訊28at.com

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

重量級鎖,指向互斥量的指針。其實synchronized是重量級鎖,也就是說Synchronized的對象鎖,Mark Word鎖標識位為10,其中指針指向的是Monitor對象的起始地址。xHe28資訊網——每日最新資訊28at.com

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

在JDK1.6之前,synchronized的實現直接調用ObjectMonitor的enter和exit,這種鎖被稱之為重量級鎖。從JDK6開始,HotSpot虛擬機開發團隊對Java中的鎖進行優化,如增加了適應性自旋、鎖消除、鎖粗化、輕量級鎖和偏向鎖等優化策略,提升了synchronized的性能。xHe28資訊網——每日最新資訊28at.com

  • 偏向鎖:在無競爭的情況下,只是在Mark Word里存儲當前線程指針,CAS操作都不做。
  • 輕量級鎖:在沒有多線程競爭時,相對重量級鎖,減少操作系統互斥量帶來的性能消耗。但是,如果存在鎖競爭,除了互斥量本身開銷,還額外有CAS操作的開銷。
  • 自旋鎖:減少不必要的CPU上下文切換。在輕量級鎖升級為重量級鎖時,就使用了自旋加鎖的方式
  • 鎖粗化:將多個連續的加鎖、解鎖操作連接在一起,擴展成一個范圍更大的鎖。
  • 鎖消除:虛擬機即時編譯器在運行時,對一些代碼上要求同步,但是被檢測到不可能存在共享數據競爭的鎖進行消除。

線程有哪些狀態

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

  • New:線程對象創建之后、但還沒有調用start()方法,就是這個狀態。
  • Runnable:它包括就緒(ready)和運行中(running)兩種狀態。如果調用start方法,線程就會進入Runnable狀態。它表示我這個線程可以被執行啦(此時相當于ready狀態),如果這個線程被調度器分配了CPU時間,那么就可以被執行(此時處于running狀態)。
  • Blocked:阻塞的(被同步鎖或者IO鎖阻塞)。表示線程阻塞于鎖,線程阻塞在進入synchronized關鍵字修飾的方法或代碼塊(等待獲取鎖)時的狀態。比如前面有一個臨界區的代碼需要執行,那么線程就需要等待,它就會進入這個狀態。它一般是從RUNNABLE狀態轉化過來的。如果線程獲取到鎖,它將變成RUNNABLE狀態。
  • WAITING : 永久等待狀態,進入該狀態的線程需要等待其他線程做出一些特定動作(比如通知)。處于該狀態的線程不會被分配CPU執行時間,它們要等待被顯式地喚醒,否則會處于無限期等待的狀態。一般Object.wait。
  • TIMED_WATING: 等待指定的時間重新被喚醒的狀態。有一個計時器在里面計算的,最常見就是使用Thread.sleep方法觸發,觸發后,線程就進入了Timed_waiting狀態,隨后會由計時器觸發,再進入Runnable狀態。
  • 終止(TERMINATED):表示該線程已經執行完成。

CountDownLatch與CyclicBarrier 區別

CountDownLatch和CyclicBarrier都用于讓線程等待,達到一定條件時再運行。主要區別是:xHe28資訊網——每日最新資訊28at.com

  • CountDownLatch:一個或者多個線程,等待其他多個線程完成某件事情之后才能執行;
  • CyclicBarrier:多個線程互相等待,直到到達同一個同步點,再繼續一起執行。

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

多線程環境下的偽共享

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

CPU的緩存是以緩存行(cache line)為單位進行緩存的,當多個線程修改相互獨立的變量,而這些變量又處于同一個緩存行時就會影響彼此的性能。這就是偽共享xHe28資訊網——每日最新資訊28at.com

現代計算機計算模型:xHe28資訊網——每日最新資訊28at.com

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

  • CPU執行速度比內存速度快好幾個數量級,為了提高執行效率,現代計算機模型演變出CPU、緩存(L1,L2,L3),內存的模型。
  • CPU執行運算時,如先從L1緩存查詢數據,找不到再去L2緩存找,依次類推,直到在內存獲取到數據。
  • 為了避免頻繁從內存獲取數據,聰明的科學家設計出緩存行,緩存行大小為64字節。

也正是因為緩存行的存在,就導致了偽共享問題,如圖所示:xHe28資訊網——每日最新資訊28at.com

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

假設數據a、b被加載到同一個緩存行。xHe28資訊網——每日最新資訊28at.com

  • 當線程1修改了a的值,這時候CPU1就會通知其他CPU核,當前緩存行(Cache line)已經失效。
  • 這時候,如果線程2發起修改b,因為緩存行已經失效了,所以「core2 這時會重新從主內存中讀取該 Cache line 數據」。讀完后,因為它要修改b的值,那么CPU2就通知其他CPU核,當前緩存行(Cache line)又已經失效。
  • 所以,如果同一個Cache line的內容被多個線程讀寫,就很容易產生相互競爭,頻繁回寫主內存,會大大降低性能。

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

解決偽共享問題的一種方法是通過填充(Padding)來確保共享的變量獨立存儲于不同的緩存行中。填充的思想是在變量之間插入一些無關的數據,使它們分布到不同的緩存行,從而避免多個變量共享同一個緩存行。xHe28資訊網——每日最新資訊28at.com

在Java中,可以使用@Contended注解來避免偽共享。這個注解可以在字段上使用,它會在字段的前后插入填充,使得字段單獨占據一個緩存行。xHe28資訊網——每日最新資訊28at.com

Fork/Join框架

Fork/Join框架是Java7提供的一個用于并行執行任務的框架,是一個把大任務分割成若干個小任務,最終匯總每個小任務結果后得到大任務結果的框架。xHe28資訊網——每日最新資訊28at.com

Fork/Join框架需要理解兩個點,「分而治之」和「工作竊取」。xHe28資訊網——每日最新資訊28at.com

分而治之

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

工作竊取

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

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

一般就是指做得快的線程(盜竊線程)搶慢的線程的任務來做,同時為了減少鎖競爭,通常使用雙端隊列,即快線程和慢線程各在一端。xHe28資訊網——每日最新資訊28at.com

ThreadLocal原理

ThreadLocal的內存結構圖:xHe28資訊網——每日最新資訊28at.com

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

  • Thread線程類有一個類型為ThreadLocal.ThreadLocalMap的實例變量threadLocals,即每個線程都有一個屬于自己的ThreadLocalMap。
  • ThreadLocalMap內部維護著Entry數組,每個Entry代表一個完整的對象,key是ThreadLocal本身,value是ThreadLocal的泛型值。
  • 并發多線程場景下,每個線程Thread,在往ThreadLocal里設置值的時候,都是往自己的ThreadLocalMap里存,讀也是以某個ThreadLocal作為引用,在自己的map里找對應的key,從而可以實現了線程隔離。

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

內存泄露問題:指程序中動態分配的堆內存由于某種原因沒有被釋放或者無法釋放,造成系統內存的浪費,導致程序運行速度減慢或者系統奔潰等嚴重后果。內存泄露堆積將會導致內存溢出。xHe28資訊網——每日最新資訊28at.com

ThreadLocal的內存泄露問題一般考慮和Entry對象有關,ThreadLocal::Entry被弱引用所修飾。JVM會將弱引用修飾的對象在下次垃圾回收中清除掉。這樣就可以實現ThreadLocal的生命周期和線程的生命周期解綁。但實際上并不是使用了弱引用就會發生內存泄露問題,考慮下面幾個過程:xHe28資訊網——每日最新資訊28at.com

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

當ThreadLocal Ref被回收了,由于在Entry使用的是強引用,在Current Thread還存在的情況下就存在著到達Entry的引用鏈,無法清除掉ThreadLocal的內容,同時Entry的value也同樣會被保留;也就是說就算使用了強引用仍然會出現內存泄露問題。xHe28資訊網——每日最新資訊28at.com

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

當ThreadLocal Ref被回收了,由于在Entry使用的是弱引用,因此在下次垃圾回收的時候就會將ThreadLocal對象清除,這個時候Entry中的KEY=null。但是由于ThreadLocalMap中任然存在Current Thread Ref這個強引用,因此Entry中value的值任然無法清除。還是存在內存泄露的問題。xHe28資訊網——每日最新資訊28at.com

AQS實現原理

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

AbstractQueuedSynchronizer(AQS)是Java中用于構建同步器的基礎框架。它提供了一個靈活的、可重用的同步器實現,可以用來構建各種同步工具,如ReentrantLock、Semaphore、CountDownLatch等。AQS的核心思想是基于FIFO等待隊列,通過狀態(state)來管理線程的同步。xHe28資訊網——每日最新資訊28at.com

核心原理:xHe28資訊網——每日最新資訊28at.com

  • State(狀態): AQS 的同步狀態是一個整數,表示被同步的資源的狀態。不同的同步器會使用不同的方式來表示狀態的含義,例如,ReentrantLock 使用 state 表示持有鎖的線程的數量,Semaphore 使用 state 表示可用的許可數量等。
  • FIFO 等待隊列: AQS 使用一個FIFO的等待隊列來管理獲取同步資源失敗的線程。每個節點(Node)表示一個等待線程,節點中保存了等待狀態、前驅節點、后繼節點等信息。當一個線程嘗試獲取鎖但失敗時,它會被包裝成一個節點并加入到等待隊列中。
  • 獨占模式和共享模式: AQS 支持獨占模式和共享模式。獨占模式表示只有一個線程能夠獲取同步資源,如ReentrantLock 就是獨占模式的同步器。共享模式表示多個線程可以同時獲取同步資源,如Semaphore 就是共享模式的同步器。AQS 使用 acquire 和 release 方法來分別表示獲取和釋放同步資源。
  • acquire 方法: 當線程嘗試獲取同步資源時,它會調用 AQS 的 acquire 方法。acquire 方法會根據同步狀態的不同情況進行處理,如果同步狀態允許當前線程獲取資源,則直接返回;否則,當前線程會被包裝成節點并加入到等待隊列中,然后進入自旋等待狀態,直到獲取到資源。
  • release 方法: 當線程釋放同步資源時,它會調用 AQS 的 release 方法。release 方法會根據同步狀態的不同情況進行處理,然后喚醒等待隊列中的下一個線程,使其有機會獲取資源。
  • 獨占鎖和共享鎖的實現: AQS 提供了獨占鎖的實現方法 tryAcquire 和 tryRelease,以及共享鎖的實現方法 tryAcquireShared 和 tryReleaseShared。

ReentrantLock 解析:xHe28資訊網——每日最新資訊28at.com

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

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

上下文切換

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

CPU上下文:CPU 寄存器,是CPU內置的容量小、但速度極快的內存。而程序計數器,則是用來存儲 CPU 正在執行的指令位置、或者即將執行的下一條指令位置。它們都是 CPU 在運行任何任務前,必須的依賴環境,因此叫做xHe28資訊網——每日最新資訊28at.com

CPU上下文切換:把前一個任務的CPU上下文(也就是CPU寄存器和程序計數器)保存起來,然后加載新任務的上下文到這些寄存器和程序計數器,最后再跳轉到程序計數器所指的新位置,運行新任務。xHe28資訊網——每日最新資訊28at.com

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

  • 分時調度:讓所有的線程輪流獲得CPU的使用權,并且平均分配每個線程占用的 CPU 的時間片。
  • 搶占式調度:優先讓可運行池中優先級高的線程占用CPU,如果可運行池中的線程優先級相同,那么就隨機選擇一個線程,使其占用CPU。處于運行狀態的線程會一直運行,直至它不得不放棄 CPU。

本文鏈接:http://www.www897cc.com/showinfo-26-58945-0.html深入理解與應用多線程技術

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

上一篇: Vue3.js組件通信,兄弟組件、父子、祖孫組件間通信

下一篇: 程序開發中使用XML還是JSON作為數據傳輸格式好?

標簽:
  • 熱門焦點
  • MIX Fold3包裝盒泄露 新機本月登場

    小米的全新折疊屏旗艦MIX Fold3將于本月發布,近日該機的真機包裝盒在網上泄露。從圖上來看,新的MIX Fold3包裝盒在外觀設計方面延續了之前的方案,變化不大,這也是目前小米旗艦
  • 容量越大越不壞?24萬塊硬盤故障率報告公布 這些產品零故障

    8月5日消息,云存儲服務商Backblaze發布了最新的硬盤故障率報告,年故障率有所上升。Backblaze發布的硬盤季度統計數據,其中包括故障率等重要方面。這些結
  • 三言兩語說透設計模式的藝術-簡單工廠模式

    一、寫在前面工廠模式是最常見的一種創建型設計模式,通常說的工廠模式指的是工廠方法模式,是使用頻率最高的工廠模式。簡單工廠模式又稱為靜態工廠方法模式,不屬于GoF 23種設計
  • 虛擬鍵盤 API 的妙用

    你是否在遇到過這樣的問題:移動設備上有一個固定元素,當激活虛擬鍵盤時,該元素被隱藏在了鍵盤下方?多年來,這一直是 Web 上的默認行為,在本文中,我們將探討這個問題、為什么會發生
  • 當家的盒馬,加速謀生

    來源 | 價值星球Planet作者 | 歸去來自己&ldquo;當家&rdquo;的盒馬,開始加速謀生了。據盒馬官微消息,盒馬計劃今年開放生鮮供應鏈,將其生鮮商品送往食堂。目前,盒馬在上海已經與
  • 阿里瓴羊One推出背后,零售企業迎數字化新解

    作者:劉曠近年來隨著數字經濟的高速發展,各式各樣的SaaS應用服務更是層出不窮,但本質上SaaS大多局限于單一業務流層面,對用戶核心關切的增長問題等則沒有提供更好的解法。在Saa
  • OPPO K11采用全方位護眼屏:三大護眼能力減輕視覺疲勞

    日前OPPO官方宣布,全新的OPPO K11將于7月25日正式發布,將主打旗艦影像,和同檔位競品相比,其最大的賣點就是將配備索尼IMX890主攝,堪稱是2000檔位影像表
  • 機構稱Q2全球智能手機出貨量同比下滑11% 蘋果份額依舊第2

    7月20日消息,據外媒報道,研究機構的報告顯示,由于需求下滑,今年二季度全球智能手機的出貨量,同比下滑了11%,三星、蘋果等主要廠商的銷量,較去年同期均有下
  • 蘋果MacBook Pro 2021測試:仍不支持平滑滾動

    據10月30日9to5 Mac 消息報道,蘋果新的 14 英寸和 16 英寸 MacBook Pro 2021 上市后獲得了不錯的評價,亮點包括行業領先的性能,令人印象深刻的電池續航,精美豐
Top 主站蜘蛛池模板: 东辽县| 安塞县| 遵义市| 建水县| 九江市| 华阴市| 邮箱| 沙坪坝区| 甘德县| 自治县| 吴江市| 西宁市| 东海县| 北海市| 通道| 竹山县| 札达县| 清流县| 阳东县| 左权县| 临沂市| 鄂州市| 克拉玛依市| 临洮县| 太谷县| 微博| 抚宁县| 肥西县| 团风县| 会昌县| 彩票| 车致| 新乐市| 互助| 谢通门县| 公安县| 连南| 玉山县| 长顺县| 淮北市| 内乡县|