我需要优先构建我称之为“Unfair Semaphore”的东西。
例如:当具有priority = 1
的线程想要获取信号量时,它只需要等到具有相同优先级的另一个线程完成,然后它就可以acquire()
。但是当priority = 2
的线程想要获取信号量时,它必须等待所有priority = 1
的线程在使用信号量之前完成,然后尝试acquire()
。
我总共有4个不同的优先事项。
这是我尝试的但是没有用。
有人有解决方案吗?
public class UnfairSemaphore
{
private Semaphore mPrior1;
private Semaphore mPrior2;
private Semaphore mPrior3;
private Semaphore mPrior4;
public UnfairSemaphore()
{
mPrior1 = new Semaphore(1);
mPrior2 = new Semaphore(1);
mPrior3 = new Semaphore(1);
mPrior4 = new Semaphore(1);
}
public void acquire(int priority) throws InterruptedException
{
if(priority == 1)
{
mPrior1.acquire();
}
else if(priority == 2)
{
while(mPrior1.hasQueuedThreads() && mPrior1.availablePermits() <=0)
{
//wait();
}
mPrior2.acquire();
mPrior1.acquire();
}
else if(priority == 3)
{
while(mPrior1.hasQueuedThreads() && mPrior1.availablePermits() <=0 && mPrior2.hasQueuedThreads() && mPrior2.availablePermits() <=0)
{
//wait();
}
mPrior3.acquire();
mPrior2.acquire();
mPrior1.acquire();
}
else
{
while(mPrior1.hasQueuedThreads() && mPrior1.availablePermits() <=0 && mPrior2.hasQueuedThreads() && mPrior2.availablePermits() <=0 && mPrior3.hasQueuedThreads() && mPrior3.availablePermits() <=0)
{
//wait();
}
mPrior4.acquire();
mPrior3.acquire();
mPrior2.acquire();
mPrior1.acquire();
}
}
public void release(int priority)
{
if(priority == 1)
{
mPrior1.release();
}
else if(priority == 2)
{
mPrior1.release();
mPrior2.release();
}
else if(priority == 3)
{
mPrior1.release();
mPrior2.release();
mPrior3.release();
}
else
{
mPrior1.release();
mPrior2.release();
mPrior3.release();
mPrior4.release();
}
//notifyAll();
}
}
答案 0 :(得分:0)
基本要求是,我们有一堆等待线程,每个线程都有一个优先级。在release()
上,我们选择具有最高优先级的等待线程,并将其唤醒。
这可以通过LockSupport中的主题park()
和unpark()
来完成。它是一种低级并发工具,但我们不会将它用于精英;我们使用它是因为它最自然地模拟我们的解决方案。
首先,我们需要一个存储等待线程及其优先级的数据结构。你可以通过很多方式做到这一点。
void storeWaitingThread(Integer priority, Thread thread) { ... }
// select and remove a waiting thread with highest priority; return null if none.
Thread selectWaitingThread(){ ... }
现在,release()
只会选择一个等待的帖子并unpark
final Object lock = new Object();
volatile Thread owningThread;
public void release()
{
synchronized (lock)
{
Thread nextOwner = selectWaitingThread();
owningThread = nextOwner;
}
LockSupport.unpark(owningThread);
}
acquire(priority)
将当前线程存储为等待线程;停车直到被选中
public void acquire(int priority)
{
Thread thisThread = Thread.currentThread();
synchronized (lock)
{
if(owningThread==null)
{
owningThread=thisThread;
return;
}
storeWaitingThread(priority, thisThread);
}
while(owningThread!=thisThread)
{
LockSupport.park();
// interrupt ignored. // todo handle interrupt
}
}
请参阅https://gist.github.com/zhong-j-yu/3ea91194f55d91059789
的完整代码请注意,我们的acquire
会忽略中断。如果它应该在中断时保释,请在park()
唤醒后添加一些逻辑。
答案 1 :(得分:-1)
为什么要自己管理线程?
您应该使用Thread类中的synchronised
关键字和setPriority
方法。
请查看以下链接:
https://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html#setPriority%28int%29
https://docs.oracle.com/javase/tutorial/essential/concurrency/syncmeth.html