【十八掌●基本功篇】第一掌:Java之多線程--信號量

這一篇博文是【大數據技術●降龍十八掌】系列文章的其中一篇,點擊查看目錄:這裏寫圖片描述大數據技術●降龍十八掌


信號量(Semaphore)是可以定義共享資源的個數,允許多個線程同時使用共享資源,在信號量內部有一個計數器,當有線程訪問資源時候,計數器將自動遞減,當它爲0時,不再允許其他線程對共享資源訪問,只到有一個線程釋放共享資源,這樣就完成就共享資源的保護。定義N個長度信號量(Semaphore)可以理解爲定義了N個令牌,每個線程只有拿到令牌後才能使用資源,當使用資源完畢後,歸還令牌。

看一個實例:

import java.util.Date;
import java.util.concurrent.Semaphore;

/**
 * Created by 鳴宇淳 on 2017/12/26.
 */
public class Demo1 {

    //定義一個20長度的Semaphore信號量
    private static Semaphore semaphore = new Semaphore(20);

    public static void main(String[] args) {
        ThreadDemo threadDemo1 = new ThreadDemo(semaphore, 10);
        ThreadDemo threadDemo2 = new ThreadDemo(semaphore, 16);
        ThreadDemo threadDemo3 = new ThreadDemo(semaphore, 5);

        Thread t1 = new Thread(threadDemo1, "線程1");
        Thread t2 = new Thread(threadDemo2, "線程2");
        Thread t3 = new Thread(threadDemo3, "線程3");

        t1.start();
        t2.start();
        t3.start();

    }

    static class ThreadDemo implements Runnable {
        private int num;
        private Semaphore semaphore;

        public ThreadDemo(Semaphore semaphore, int num) {
            this.num = num;
            this.semaphore = semaphore;
        }

        public void run() {
            try {
                System.out.println(new Date() + Thread.currentThread().getName() + "申請獲得" + this.num + "個令牌");
                //佔用num個令牌
                semaphore.acquire(this.num);
                System.out.println(new Date() + Thread.currentThread().getName() + "[已經]得到" + this.num + "個令牌.......");

                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                //釋放num個令牌
                semaphore.release(this.num);
                System.out.println(new Date() + Thread.currentThread().getName() + "釋放" + this.num + "個令牌++++++++");
            }
        }
    }
}

輸出:

Tue Dec 26 19:03:26 CST 2017線程2申請獲得16個令牌
Tue Dec 26 19:03:26 CST 2017線程1申請獲得10個令牌
Tue Dec 26 19:03:26 CST 2017線程3申請獲得5個令牌
Tue Dec 26 19:03:26 CST 2017線程2[已經]得到16個令牌.......
Tue Dec 26 19:03:28 CST 2017線程2釋放16個令牌++++++++
Tue Dec 26 19:03:28 CST 2017線程3[已經]得到5個令牌.......
Tue Dec 26 19:03:28 CST 2017線程1[已經]得到10個令牌.......
Tue Dec 26 19:03:30 CST 2017線程1釋放10個令牌++++++++
Tue Dec 26 19:03:30 CST 2017線程3釋放5個令牌++++++++

這個例子中,一共有20個令牌,線程1、線程2、線程3都去申請令牌,線程2首先領到16個令牌,還剩下4個,不滿足線程2和線程1的需求,他們兩個只能等待,當線程2釋放了16個令牌後,首先分配給線程3令牌,還剩下17個,也滿足線程1的10個需求,所以也分配給了線程1,當他們使用結束後,就都歸還了令牌。
領取令牌使用acquire()方法,歸還令牌使用release()方法,一定要記得將歸還令牌的代碼放入finally中,以保證肯定能歸還。

發佈了74 篇原創文章 · 獲贊 77 · 訪問量 5萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章