信号量中的Java优先级
我有多个线程访问一个外部资源–broswer。但一次只能有一个线程访问它。因此,我使用一个信号量来同步它们。但是,一个线程从GUI获取输入,然后访问浏览器获取结果,它应该比其他线程具有优先级,我不知道如何使用信号量来实现它 我在想,每个线程在获取信号量后都会检查队列中是否有优先级线程在等待,如果是,则会释放它并再次等待。只有优先级线程在获取后才释放它信号量中的Java优先级,java,multithreading,semaphore,Java,Multithreading,Semaphore,我有多个线程访问一个外部资源–broswer。但一次只能有一个线程访问它。因此,我使用一个信号量来同步它们。但是,一个线程从GUI获取输入,然后访问浏览器获取结果,它应该比其他线程具有优先级,我不知道如何使用信号量来实现它 我在想,每个线程在获取信号量后都会检查队列中是否有优先级线程在等待,如果是,则会释放它并再次等待。只有优先级线程在获取后才释放它 这是一个好的解决方案,还是Java API中还有其他东西我可以使用?您在这里混淆了概念 信号量只是“同步”线程交互的众多选项之一。它们与线程优先级
这是一个好的解决方案,还是Java API中还有其他东西我可以使用?您在这里混淆了概念 信号量只是“同步”线程交互的众多选项之一。它们与线程优先级和线程调度无关 另一方面,线程优先级本身就是一个主题。你在Java中有办法影响他们;但这些行动的结果在很大程度上取决于底层平台/操作系统;以及JVM实现本身。从理论上讲,使用这些优先权是可行的,但正如所说的那样;现实更重要
换句话说:您只能使用信号量来确保在一个时间点上只有一个线程在使用您的队列。当CPU周期成为一个问题时,它根本无助于确保您的GUI读取线程胜过其他线程。但如果你幸运的话,你的问题的答案将是简单的电话;使用不同的优先级。Java中没有同步原语可以让您以自己想要的方式将一个线程优先于其他线程 但是你可以用另一种方法来解决你的问题。不要同步线程,而是让它们生成小任务(例如,
Runnable
对象),并将这些任务放入PriorityBlockingQueue
,其中来自GUI线程的任务具有最高优先级。单个工作线程将轮询此队列中的任务并执行它们。这将保证相互排斥和优先次序
ThreadPoolExecutor
中有接受阻塞队列的特殊构造函数。因此,您所需要的就是这样一个执行器,它带有一个与您的PriorityBlockingQueue
一起提供的线程。然后将您的任务提交给该执行者,它将处理其余的任务
如果你决定选择这种方法,你可能会对这篇文章感兴趣:这里有一个简单的、没有虚饰的答案。这类似于读/写锁的工作方式,只是每个锁都有独占访问权(通常所有读卡器并行进行)。请注意,它不使用信号量,因为这几乎总是使用错误的构造
public class PrioLock {
private boolean _locked;
private boolean _priorityWaiting;
public synchronized void lock() throws InterruptedException {
while(_locked || _priorityWaiting) {
wait();
}
_locked = true;
}
public synchronized void lockPriority() throws InterruptedException {
_priorityWaiting = true;
try {
while(_locked) {
wait();
}
_locked = true;
} finally {
_priorityWaiting = false;
}
}
public synchronized void unlock() {
_locked = false;
notifyAll();
}
}
您可以像使用java.util.concurrent中的锁类型一样使用它:
普通螺纹:
_prioLock.lock();
try {
// ... use resource here ...
} finally {
_prioLock.unlock();
}
“优先级”线程:
更新:
对“抢占式”线程交互评论的回应:
一般来说,你不能这样做。您可以构建自定义功能,将“暂停点”添加到锁定部分,这将允许低优先级线程向高优先级线程屈服,但这将充满危险
实际上,您唯一能做的就是中断工作线程,使其退出锁定的代码块(假设您的工作代码响应了中断)。这将允许高优先级线程以低优先级线程丢失正在进行的工作为代价更快地进行(并且您可能还必须实现回滚逻辑)
为了实现这一点,您需要:
lockPriority()
中,如果发现“当前线程”,则中断该线程lock()
/unlock()
(低优先级)调用之间实现逻辑,以便:
lock()
/unlock()
(低优先级)调用之外实现“重试”逻辑,以便重新执行中断时丢失的任何工作不涉及术语,我们如何才能真正解决OP想要的问题?i、 例如,一个“类似信号量”的资源访问控制结构,它本机理解优先级。我们为什么要这样做?严肃地说:优先级和同步是两种不同的职责。在我看来,把两者都推到一件事情上是完全错误的。就因为他想要点什么。。。但这并不意味着给他那将是正确的解决方案!我的意思是,我不认为应该把重点放在使用信号量来解决线程优先级问题上。线程优先级和锁优先级也是两个不同的概念,我相信你在这里混淆了它们。读/写锁是一种具有简单优先级机制的锁定形式(writer优先于readers)。OP真的在寻找一个类似的概念(除了读/写锁不同之外,所有的储物柜都应该是独占的);请用另一个答案回答;-)调用
lockPriority()
时,我们是否可以中断正在运行的线程,让优先级线程完成,然后恢复以前运行的任务,而不是等待\u locked
comment@jtahlborn我喜欢这个答案。。。不过,等待可能应该是一个计数器,而不是boolean@Duane-OP声明只有一个优先级线程(这是一个“简单、无虚饰的答案”)。如果您想将其推广到可以有多个优先级线程的解决方案中,那么,是的,\u priorityWaiting需要是一个计数器。你也可以有多个级别的p
_prioLock.lockPriority();
try {
// ... use resource here ...
} finally {
_prioLock.unlock();
}