文档章节

Java并发编程中级篇(一):使用Semaphore信号量进行并发控制

阿拉德大陆的魔法师
 阿拉德大陆的魔法师
发布于 2016/11/25 16:25
字数 691
阅读 129
收藏 0

Semaphore是一个二进制信号量,只有0和1两个值。如果线程想要访问一个共享资源,它必须先获得信号量。如果信号量的内部计数器大于0,那么信号量减1,并允许访问这个资源。否则,如果信号量计数器等于0,线程会等待直至计数器大于0。

所以说计数器大于0,说明有资源可用。计数器等于0,说明没有资源可用。

同时Semaphore提供了一个带有boolean参数的构造方法,true代表公平锁,false代表非公平锁,默认实现是非公平锁。

我们使用Semaphore信号量来重写PrintQueue的例子。

首先实现一个PrintQueue打印队列,有一个Semaphore信号量用来并发访问控制。打印之前使用acquire()方法获取信号量,执行完毕后使用release()方法释放信号量。每次打印等待一个随机时间,模拟打印耗时。

public class PrintQueue {
    private Semaphore semaphore;

    public PrintQueue() {
        //semaphore = new Semaphore(1);   //非公平的
        semaphore = new Semaphore(1, true); //公平的
    }

    public void printJob(Object document) {
        try {
            semaphore.acquire();
            long duration = (long)(Math.random() * 10000);
            System.out.printf("%s: Print a job duration %d seconds.\n",
                    Thread.currentThread().getName(), duration / 1000);
            Thread.sleep(duration);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            semaphore.release();
        }
    }
}

创建Job线程类,模拟打印请求。

public class Job implements Runnable{
    private PrintQueue printQueue;

    public Job(PrintQueue printQueue) {
        this.printQueue = printQueue;
    }

    @Override
    public void run() {
        System.out.printf("%s: Going to print a Job.\n", Thread.currentThread().getName());
        printQueue.printJob(new Object());
        System.out.printf("%s: The Job has been printed.\n", Thread.currentThread().getName());
    }
}

主方法类中启动10个打印Job线程。

public class Main {
    public static void main(String[] args) {
        PrintQueue printQueue = new PrintQueue();

        Thread[] threads = new Thread[10];
        for (int i = 1; i < 10; i++) {
            threads[i] = new Thread(new Job(printQueue));
        }

        for (int i = 1; i < 10; i++) {
            threads[i].start();
        }
    }
}

查看日志,每次只有一个打印Job可以执行打印程序,其他线程处于WAITING状态。

Thread-0: Going to print a Job.
Thread-8: Going to print a Job.
Thread-7: Going to print a Job.
Thread-6: Going to print a Job.
Thread-5: Going to print a Job.
Thread-4: Going to print a Job.
Thread-0: Print a job duration 2 seconds.
Thread-3: Going to print a Job.
Thread-2: Going to print a Job.
Thread-1: Going to print a Job.
Thread-0: The Job has been printed.
Thread-8: Print a job duration 8 seconds.
Thread-8: The Job has been printed.
Thread-7: Print a job duration 8 seconds.
Thread-7: The Job has been printed.
Thread-6: Print a job duration 9 seconds.
Thread-6: The Job has been printed.
Thread-5: Print a job duration 6 seconds.
Thread-5: The Job has been printed.
Thread-4: Print a job duration 7 seconds.
Thread-4: The Job has been printed.
Thread-3: Print a job duration 4 seconds.
Thread-3: The Job has been printed.
Thread-2: Print a job duration 1 seconds.
Thread-2: The Job has been printed.
Thread-1: Print a job duration 1 seconds.
Thread-1: The Job has been printed.

 

© 著作权归作者所有

共有 人打赏支持
阿拉德大陆的魔法师
粉丝 26
博文 91
码字总数 83019
作品 0
西城
程序员
私信 提问
Dubbo源码之服务端并发控制——ExecuteLimitFilter

上一篇关于《Dubbo客户端并发控制——ActiveLimitFilter》 作用,设计原理,及配置方式。 这篇是关于Dubbo服务端Filter组件扩展 ExecuteLimitFilter ,它可以限制服务端的方法级别的并发处理...

键走偏锋
2018/08/25
0
0
读书笔记之《Java并发编程的艺术》-并发编程容器和框架(重要)

读书笔记部分内容来源书出版书,版权归本书作者,如有错误,请指正。 欢迎star、fork,读书笔记系列会同步更新 git https://github.com/xuminwlt/j360-jdk module j360-jdk-thread/me.j360....

Hi徐敏
2015/11/11
0
1
JAVA多线程--信号量(Semaphore)

简介 信号量(Semaphore),有时被称为信号灯,是在多线程环境下使用的一种设施, 它负责协调各个线程, 以保证它们能够正确、合理的使用公共资源。 一个计数信号量。从概念上讲,信号量维护了一...

cloud-coder
2015/01/01
0
4
PV操作和信号量机制实现进程同步(对多个临界资源的互斥访问)

进程同步是我们在多线程中讨论最多的一个话题,在大多数的开发语言中,他们都有自己实现进程同步的方法或者实现。但归根结底他们实现的方式都是基于操作系统的进程同步的方式。今天我们就一起...

长平狐
2012/11/12
676
0
Java线程面试题 Top 50

不管你是新程序员还是老手,你一定在面试中遇到过有关线程的问题。Java语言一个重要的特点就是内置了对并发的支持,让Java大受企业和程序员的欢迎。大多数待遇丰厚的Java开发职位都要求开发者...

loda0128
2015/05/29
0
0

没有更多内容

加载失败,请刷新页面

加载更多

求推广,德邦快递坑人!!!!

完全没想好怎么来吐槽自己这次苦逼的德邦物流过程了,只好来记一个流水账。 从寄快递开始: 2019年1月15日从 德邦物流 微信小app上下单,截图如下: 可笑的是什么,我预约的是17号上门收件,...

o0无忧亦无怖
昨天
3
0
Mac Vim配置

1.升级 vim   我自己 MacBook Pro 的系统还是 10.11 ,其自带的 vim 版本为 7.3 ,我们将其升至最新版: 使用 homebrew : brew install vim --with-lua --with-override-system-vim 这将下...

Pasenger
昨天
4
0
vmware安装Ubuntu上不了网?上网了安装不了net-tools,无法执行ifconfig?

1.重新设置网络适配器还是不行,如下指定nat 2.还需要指定共享网络,我是在无线环境下 3.无法执行ifconfig https://packages.ubuntu.com/bionic/net-tools到这个网站下载net-tools的deb文件...

noob_chr
昨天
1
0
解决SVN:E210007无法协商认证机制

svn:E210007 svn: Cannot negotiate authentication mechanism 执行下面代码即可 sudo yum install cyrus-sasl cyrus-sasl-plain cyrus-sasl-ldap...

临江仙卜算子
昨天
2
0
java8的时间和`Date`的对比

java8的时间和Date的对比 java8提供了新的时间接口。相对Date,Calendar,个人感觉最大的好处是对时间操作的学习成本很低,比Calendar低。 1. LocalDate,LocalTime,LocalDateTime LocalDate 代...

北风刮的不认真了
昨天
3
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部