java保證多線程的執行順序


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

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

比如一個main方法里面先后運行thread1,,thread2,thread3,那么thread1.start()之后,運行thread1.join(),這是會讓主線程mian等待新的線程thread1執行完了,再執行主線程mian下面的代碼,thread1.join()是然主線程main wait。

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定義了線程和主內存之間的一個關系。線程之間通訊,必須通過主內存通訊。

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

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做了很多優化,性能差異不大。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM