[英]Semaphores not avoiding thread loss
這是我在這里的第一個問題,所以請多多包涵。
我目前正在 Java 中進行關於多線程和並發的 UNI 分配,我們被要求使用不同的線程鎖定方法實現各種版本的“呼叫中心”,其中一種是信號量。 我將直接進入代碼以顯示我的問題是什么:
制片人Class:
public final class Caller implements Runnable {
private final CallCenter callCenter;
public Caller(long id, CallCenter callCenter) {
this.callCenter = callCenter;
}
@Override
public void run() {
try {
callCenter.receive(new Call());
} catch(Exception ex) {
throw new RuntimeException(ex);
}
}
}
消費者 Class:
public final class Operator implements Runnable {
private final CallCenter callCenter;
private Call call;
public Operator(CallCenter callCenter) {
this.callCenter = callCenter;
}
@Override
public void run() {
try {
this.call = callCenter.answer();
} catch(InterruptedException ex) {
throw new RuntimeException(ex);
}
}
public Call getCall() {
return this.call;
}
}
服務:
import java.util.Queue;
import java.util.concurrent.Semaphore;
import java.util.LinkedList;
public final class BoundedCallCenterSemaphore implements BoundedCallCenter {
private final Queue<Call> pendingCalls = new LinkedList<Call>();
private Semaphore semaphore = new Semaphore(MAX_NUMBER_OF_PENDING_CALLS, true);
public void receive(Call call) throws Exception {
semaphore.acquire();
pendingCalls.add(call);
}
public Call answer() throws InterruptedException {
semaphore.release();
return pendingCalls.poll();
}
}
調用實現:
import java.util.concurrent.atomic.AtomicLong;
public final class Call {
private static final AtomicLong currentId = new AtomicLong();
private final long id = currentId.getAndIncrement();
public long getId() {
return id;
}
}
免責聲明
我知道我可能沒有按照預期的方式使用信號量,但是閱讀官方文檔和其他博客/答案根本沒有幫助。 我們有以下限制:只修改Service Class,使用Semaphore解決並且只使用Semaphore.acquire()和Semaphore.receive()避免競速和忙等待,不允許其他方法或線程鎖定結構
實際問題:
我將避免在這里發布我們教授編寫的全部測試,只知道向服務發送了 100 個調用,為簡單起見,每個調用者只調用一次,每個接線員只響應一次。 當在沒有信號量的情況下實現呼叫中心時,您會遇到由 while 循環產生的繁忙等待,並且並發性管理不善,因為如果不同的線程同時操作,某些調用可能會被應答兩次或更多次。 這里的任務是消除繁忙的等待,並確保每個呼叫只接收和應答一次。 我嘗試使用上面報告的信號量,雖然消除了忙碌等待,但一些呼叫最終根本沒有得到應答。 關於我做錯了什么的任何建議? 如何確保每個電話只接聽一次?
最后,我使用了三個信號量。 當pendingCalls.size() >= MAX_NUMBER_OF_PENDING_CALLS
時,第一個信號量new Semaphore(MAX_NUMBER_OF_PENDING_CALLS, true)
在阻塞新條目的意義上保護隊列。 第二個信號量new Semaphore(1, true)
保護生產者線程,一次只允許一個線程訪問隊列以進行添加操作。 第三個也是最后一個信號量在沒有許可的情況下開始,並等待第一個生產者線程將第一個調用插入緩沖區new Semaphore(0, true)
。
代碼
public final class BoundedCallCenterSemaphore implements BoundedCallCenter {
private final LinkedList<Call> pendingCalls = new LinkedList<Call>();
static Semaphore receiver = new Semaphore(1, true);
static Semaphore storage = new Semaphore(MAX_NUMBER_OF_PENDING_CALLS, true);
static Semaphore operants = new Semaphore(0, true);
public void receive(Call call) throws Exception {
try {
storage.acquire();
}
catch (InterruptedException e)
{
}
try {
receiver.acquire();
}
catch (InterruptedException e)
{
}
synchronized (pendingCalls) {
pendingCalls.add(call);
operants.release();
}
}
public Call answer() throws InterruptedException {
try
{
operants.acquire();
}
catch (InterruptedException e)
{
}
Call call = null;
synchronized (pendingCalls) {
call = pendingCalls.poll();
storage.release();
receiver.release();
}
return call;
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.