多線程 - 11.線程關鍵字的實現類

ReentrantLock 鎖類

RenntrantLock.java 在擴展功能上比 synchronized 強很多,它具備嗅探鎖定、多路分支通知等相關功能。

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class MyService{
    private Lock lock = new ReentrantLock();
    public void myMethod() {
        lock.lock();
        for (int i = 0; i < 3; i++) {
            System.out.println("ThreadName=" + Thread.currentThread().getName() + ", 第" + (i+1) + "進入函數");
        }
        lock.unlock();
    }
}

class ThreadA extends Thread{
    private MyService myService;
    public ThreadA(MyService myService){
        super();
        this.myService = myService;
    }

    @Override
    public void run() {
        super.run();
        myService.myMethod();
    }
}

public class test0 {
    public static void main(String[] args) {
        MyService myService = new MyService();
        Thread a = new ThreadA(myService);
        a.start();
        Thread b = new ThreadA(myService);
        b.start();
        Thread c = new ThreadA(myService);
        c.start();
    }
}

ThreadName=Thread-0, 第1進入函數
ThreadName=Thread-0, 第2進入函數
ThreadName=Thread-0, 第3進入函數
ThreadName=Thread-2, 第1進入函數
ThreadName=Thread-2, 第2進入函數
ThreadName=Thread-2, 第3進入函數
ThreadName=Thread-1, 第1進入函數
ThreadName=Thread-1, 第2進入函數
ThreadName=Thread-1, 第3進入函數

Lock 接口的函數定義

  1. void lock(); : 獲得鎖。
  2. void unlock(); : 鬆開鎖。
  3. boolean tryLock();: 只有在調用時鎖是空閒的情況下才獲取鎖。
  4. boolean tryLock(long time, TimeUnit unit) throws InterruptedException; : 如果鎖在給定的等待時間內空閒並且當前線程未被 interrupt / interrupted標記,則獲取該鎖。
  5. Condition newCondition(); : 返回綁定到此 lock() 實例的新 Condition 實例。
  6. void lockInterruptibly() throws InterruptedException; : 獲取鎖,除非當前線程是被 interrupt / interrupted 標記過的。

Lock 接口的實現類

  1. ReadLock
  2. ReadLockView
  3. ReentrantLock
  4. WriteLock
  5. WriteLockView
Condition.java 監視器接口類

關鍵字 synchronized 與 wait() / notify() / notifyAll()方法相結合可以實現等待 / 通知模式, ReentrantLock 也可以實現同樣的通能,但是需要藉助於 Condition 對象。
Condition 監視器接口類的函數定義

  1. void await() throws InterruptedException;使當前線程等待,直到發出喚醒或觸發 interrupt / interrupted 標記。
  2. boolean await(long time, TimeUnit unit) throws InterruptedException;使當前線程等待,直到發出信號或被中斷,或者指定的等待時間結束。
  3. long awaitNanos(long nanosTimeout) throws InterruptedException;使當前線程等待,直到發出信號或被中斷,或者指定的等待時間結束。
  4. void awaitUninterruptibly(); : 使當前線程等待直到發出信號。
  5. boolean awaitUntil(Date deadline) throws InterruptedException; : 使當前線程等待,直到發出信號或被中斷,或者指定的截止時間過去。
  6. void signal(); : 喚醒一個等待線程。
  7. void signalAll(); : 喚醒全部等待線程。
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class MyService{
    private Lock lock = new ReentrantLock();
    public Condition condition = lock.newCondition();

    public void await() {
        lock.lock();
        System.out.println("await 時間爲:" + System.currentTimeMillis());
        try {
            condition.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public void signal() {
        try {
            lock.lock();
            System.out.println("Signal 時間爲:" + System.currentTimeMillis());
            condition.signal();
        } finally {
            lock.unlock();
        }
    }
}

class ThreadA extends Thread{
    private MyService myService;

    public ThreadA(MyService myService) {
        super();
        this.myService = myService;
    }

    @Override
    public void run() {
        super.run();
        myService.await();
    }
}

public class test0 {

    public static void main(String[] args) {
        MyService myService = new MyService();
        ThreadA a = new ThreadA(myService);
        a.start();
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        myService.signal();
    }
}

await 時間爲:1592453263834
Signal 時間爲:1592453264833

所謂單個喚醒,即是在某類中設置多個 Condition ,並且只喚醒其中一個。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章