Java并发包:Exchanger和Semaphore

文章译自:http://tutorials.jenkov.com/java-util-concurrent/index.html
抽空翻译了一下这个教程的文章,后面会陆续放出,如有不妥,请批评指正。
转自请注明出处。

Exchanger

java.util.concurrent.Exchanger类代表的是一个会和点,这个会和点是两个线程交换对象的位置的,下图是这种机制的图示:
这里写图片描述

交换对象是通过其中的一个exchange()方法。下面是一个例子:

Exchanger exchanger = new Exchanger();

ExchangerRunnable exchangerRunnable1 =
        new ExchangerRunnable(exchanger, "A");

ExchangerRunnable exchangerRunnable2 =
        new ExchangerRunnable(exchanger, "B");

new Thread(exchangerRunnable1).start();
new Thread(exchangerRunnable2).start();

下面是 ExchangerRunnable的代码:

public class ExchangerRunnable implements Runnable{

    Exchanger exchanger = null;
    Object    object    = null;

    public ExchangerRunnable(Exchanger exchanger, Object object) {
        this.exchanger = exchanger;
        this.object = object;
    }

    public void run() {
        try {
            Object previous = this.object;

            this.object = this.exchanger.exchange(this.object);

            System.out.println(
                    Thread.currentThread().getName() +
                    " exchanged " + previous + " for " + this.object
            );
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}

输出结果是:

Thread-0 exchanged A for B
Thread-1 exchanged B for A

Semaphore(信号量)

java.util.concurrent.Semaphore类是一种计数信号量。这意味着它有两个主要的方法:

  • acquire()
  • release()

计数信号量初始化需要给定一个“许可证”。对于每次调用acquire(),同时一个许可证被带入了调用该方法的线程。对于每次调用release(),同时有一个许可证被返回给semaphore。因此, N个线程在没有调用release()的情况下,最多只能执行到acquire()方法 ,这里N指的是semaphore初始化时的许可证数量。许可证仅仅是一个简单的计数器。这里没什么花哨。

Semaphore的使用说明

信号量通常有两个用途:
1.保护临界区以免N个以上的线程一次进入。
2.在两个线程间发送信号。

保护临界区

如果使用信号量保护临界区,试图进入临界区的线程将要首先获得许可证,然后进入临界区,最后释放许可证。就像下面这样:

Semaphore semaphore = new Semaphore(1);

//critical section
semaphore.acquire();

...

semaphore.release();
在线程间发送信号

如果使用semaphore在线程间进行信号传递,经常是一个线程调用acquire()方法,另一个线程调用release()方法。
如果没有许可证,acquire()方法将会阻塞住直到一个许可证被另一个线程所释放。同样,如果没有许可证可释放给semaphore,那么release()方法也会被阻塞住。

因此协调线程间工作是可能的,例如,如果线程1插入一个对象到共享的list之后调用了acquire()方法,线程2从该list中取出对象之前需要先调用release()方法,这个过程中你必须创建了一个阻塞队列。Semaphore中有效许可证的数量与阻塞队列中能容纳最多元素的数量是一致的。

公平性(Fairness)

线程从semaphore中获取许可证的公平性是不能保障的。也就是说,不能确保第一个调用acquire()的线程就是第一个获得许可证的线程。如果一个线程在获取许可证时阻塞住了,而第二个线程正在检查是否有可利用的许可证时正好有一个许可证释放了,也许第二个线程将会在线程1之前获取许可证。

如果你想强制公平性,Semaphore类的构造方法有一个参数来判断semaphore是否应该强制公平性。强制公平性将会影响性能、并发性。因此不是必要的时候,不要使用它。

更多方法

java.util.concurrent.Semaphore 类还有更多的方法. 例如:

  • availablePermits()
  • acquireUninterruptibly()
  • drainPermits()
  • hasQueuedThreads()
  • getQueuedThreads()
  • tryAcquire()
  • Etc.

查看官方文档获取这些方法更详细的信息。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值