【十八掌●基本功篇】第一掌: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 篇原创文章 · 获赞 74 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/chybin500/article/details/78706484