java保證多線程的執行順序

1. java多線程環境中,如何保證多個線程按指定的順序執行呢?

1.1 經過thread的join方法保證多線程的順序執行, wait是讓主線程等待

好比一個main方法裏面前後運行thread1,,thread2,thread3,那麼thread1.start()以後,運行thread1.join(),這是會讓主線程mian等待新的線程thread1執行完了,再執行主線程mian下面的代碼,thread1.join()是然主線程main wait。java

package com.java.yj;

/**
 * Created by yejian on 2018/7/9.
 */
public class MultiThread {
    public static void main(String[] args) throws InterruptedException {
        Thread thread1 = new Thread(new Thread1());
        thread1.start();
        thread1.join();
        Thread thread2 = new Thread(new Thread2());
        thread2.start();
        thread2.join();
        Thread thread3 = new Thread(new Thread3());
        thread3.start();

    }

    public static class Thread1 implements Runnable{
        @Override
        public void run() {
            System.out.println("Thread1");
        }
    }

    public static class Thread2 implements Runnable{
        @Override
        public void run() {
            System.out.println("Thread2");
        }
    }

    public static class Thread3 implements Runnable{
        @Override
        public void run() {
            System.out.println("Thread3");
        }
    }

}

1.2 ExecutorService executor = Executors.newSingleThreadExecutor()

java5之後提供的一個多線程操做方法,建立一個只有一個線程的線程池操做,會建立一個線程隊列,按FIFO的順序執行裏面的線程。編程

package com.java.yj;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by yejian on 2018/7/9.
 */
public class MultiThread2 {
    public static void main(String[] args) throws InterruptedException {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        executor.submit(new Thread1());
        executor.submit(new Thread2());
        executor.submit(new Thread3());
        executor.shutdown();
    }

    public static class Thread1 implements Runnable{
        @Override
        public void run() {
            System.out.println("Thread1");
        }
    }

    public static class Thread2 implements Runnable{
        @Override
        public void run() {
            System.out.println("Thread2");
        }
    }

    public static class Thread3 implements Runnable{
        @Override
        public void run() {
            System.out.println("Thread3");
        }
    }


}

2. java中的volatile和synthronized

2.1JMM-java memory model

解決併發過程當中如何處理可見性,原子性,有序性的問題
runnable ,thread。
併發編程中的2個關鍵問題:緩存

a. 線程間如何通訊 --wait() notify() notifyAll()
a) 共享內存 -隱式通訊
b) 消息傳遞 - 顯示通訊多線程

b. 線程之間如何同步
在共享內存的併發模型中,同步是顯示作的; synchronized
在消息傳遞的併發模型中,因爲小時發送必須在消息接受以前,因此同步是隱式的併發

2.2. 定位內存可見性問題

什麼對象是內存共享的 ,什麼不是,堆內存的對象,java虛擬機棧

JMM定義了線程和主內存之間的一個關係。線程之間通信,必須經過主內存通信。jvm

volatile、synchronized
volatile 功能,聲明瞭volatile的變量,進行寫操做的時候,jvm會向處理器發送一條Lock的前綴指令,會把這個變量所在緩存行的數據寫回到系統內存。
在多處理器的狀況下,保證各個處理器緩存一致性的特色,會實現緩存一致性協議。改變了值的volatile變量,在其餘行程被指爲失效狀態其餘線程要使用這個變量,須要從新到駐村裏面去取。ide

synchronized:可重入鎖、互斥性、可見性
volatile 能夠作到原子性,可見性,不能作到複合操做的原子性性能

好比: volatile int i;
i++ 讀取i的值,給i加1,把新的值賦值給i,這個i++操做在多線程環境下是沒法保證原子性的優化

synchronized後面鎖定的對象,能夠是一個類對象,也能夠是一個成員變量。
第一個線程進來調用monitorener 和monitorexit實現,獲取對象的監視器,釋放對象監視器
後續進程過來,若是monitor尚未釋放,那麼他獲取不到這個對象的monitor,會放到一個對列裏面:synthronizedQueue。 等到對象的鎖釋放了,通知synthronizedQueue出隊列,獲取那個monitor。線程

3. Lock和synchronized

Lock是java5之後出現的,在juc包: java.util.concurrentlocks

3.1 synthronized的鎖何時釋放

1.1 獲取鎖的線程執行完了該代碼塊
    1.2 線程出現異常

3.2 synchronized的缺陷

2.1 讀寫衝突

3.3 Lock能夠主動去釋放鎖,而synchronized是被動的

ReadWriteLock
ReadLock
WriteLock
ReenterantLock可重入鎖
可中斷鎖
公平鎖 等待一個鎖的實際越長,獲取這個鎖的概率越高
ReenterantReadWriteLock 可重入讀寫鎖
Lock是java裏面的一個接口,有豐富的實現,而synchronized是java的一個關鍵字,是一個內置的功能

競爭資源激烈的狀況,Lock性能優於synchronized,可是jdk7,8對synchronized作了不少優化,性能差別不大。

相關文章
相關標籤/搜索