Toutes les classes d'implémentation connues :
AbstractQueuedLongSynchronizer ConditionObject. , AbstractQueuedSynchronizer.ConditionObject
public interface Condition
<br>
Condition
Object
surveillera-t-il les méthodes (wait
, notify
et notifyAll
) Décomposé en objets distincts, peut être utilisé en combinant ces objets avec n'importe quelle implémentation Lock
, fournissant plusieurs waitset(wait) pour chaque objet -set). Parmi eux, Lock
remplace l'utilisation des méthodes et instructions synchronized
, et Condition
remplace l'utilisation des méthodes de surveillance d'objets . Une
condition (également appelée file d'attente de conditions ou variable de condition) fournit à un fil une signification afin que, dans un certain état, une condition puisse maintenant être vraie pour un autre thread Le thread est suspendu (c'est-à-dire obligé « d'attendre ») jusqu'à ce qu'il soit notifié. Étant donné que l’accès à ces informations d’état partagé se produit dans un thread différent, il doit être protégé, de sorte qu’une certaine forme de verrouillage est associée à la condition. Les principales propriétés d'une attente sous réserve d'une condition sont : atomiquement libère le verrou associé et suspend le thread en cours, tout comme Object.wait
le fait.
Condition
L'instance est essentiellement liée à un verrou. Pour obtenir une instance pour une instance Lock
Condition
spécifique, utilisez sa méthode newCondition()
.
À titre d'exemple, supposons qu'il existe un tampon lié qui prend en charge les méthodes put
et take
. Si vous tentez d'effectuer une opération take
sur un tampon vide, le thread se bloquera jusqu'à ce qu'un élément devienne disponible ; si vous tentez d'effectuer une opération put
sur un tampon plein, le thread se bloquera jusqu'à ce que de l'espace soit disponible. , le fil aurait été bloqué. Nous aimons conserver les put
threads et les take
threads dans des ensembles d'attente séparés afin de pouvoir profiter d'une planification optimale et ne notifier qu'un seul thread à la fois lorsqu'un élément ou un espace dans le tampon devient disponible. Cela peut être fait en utilisant deux Condition
instances.
class BoundedBuffer { final Lock lock = new ReentrantLock(); final Condition notFull = lock.newCondition(); final Condition notEmpty = lock.newCondition(); final Object[] items = new Object[100]; int putptr, takeptr, count; public void put(Object x) throws InterruptedException { lock.lock(); try { while (count == items.length) notFull.await(); items[putptr] = x; if (++putptr == items.length) putptr = 0; ++count; notEmpty.signal(); } finally { lock.unlock(); } } public Object take() throws InterruptedException { lock.lock(); try { while (count == 0) notEmpty.await(); Object x = items[takeptr]; if (++takeptr == items.length) takeptr = 0; --count; notFull.signal(); return x; } finally { lock.unlock(); } } }
(La classe ArrayBlockingQueue
fournit cette fonctionnalité, il n'y a donc aucune raison d'implémenter cet exemple de classe.) Les implémentations
Condition
peuvent fournir des méthodes de surveillance différentes de celles de Object
le comportement et la sémantique, comme l'ordre garanti des notifications, ou la nécessité de maintenir un verrou lors de l'exécution des notifications. Si une mise en œuvre fournit une telle sémantique spéciale, la mise en œuvre DOIT documenter cette sémantique.
Notez que les instances Condition
sont simplement des objets simples qui peuvent elles-mêmes être utilisées comme cibles dans les instructions synchronized
et peuvent appeler leurs propres méthodes de surveillance wait
et notification
. L'obtention du verrouillage du moniteur d'une instance Condition
ou l'utilisation de ses méthodes de surveillance n'a rien à voir spécifiquement avec l'acquisition du Condition
associé à ce Lock
ou l'utilisation de ses méthodes waiting
et signalling
. Pour éviter toute confusion, il est recommandé que les instances Condition
ne soient jamais utilisées de cette manière, sauf dans leur propre implémentation.
Sauf indication contraire, le passage d'une valeur null
pour n'importe quel argument entraînera le lancement de NullPointerException
.
En attendant Condition
, un "faux réveil" est autorisé à se produire, généralement en guise de concession à la sémantique sous-jacente de la plateforme. Pour la plupart des applications, cela aura peu d'impact pratique, puisque Condition
doit toujours être attendu en boucle et tester l'instruction d'état attendue. Une implémentation est libre de supprimer d'éventuels réveils parasites, mais il est conseillé aux programmeurs d'applications de toujours supposer que ces réveils parasites peuvent se produire et donc de toujours attendre en boucle.
La mise en œuvre des trois formes d'attente conditionnelle (interruptible, ininterruptible et timeout) sur certaines plateformes, ainsi que leurs caractéristiques de performances, peuvent varier. En particulier, il peut être difficile de fournir ces fonctionnalités et de maintenir une sémantique spécifique, telle que les garanties de commande. De plus, la possibilité d'interrompre la suspension d'un thread n'est pas toujours possible sur toutes les plateformes.
Par conséquent, une implémentation n'est pas tenue de définir exactement les mêmes garanties ou sémantiques pour les trois formes d'attente, ni de prendre en charge la suspension réelle des threads d'interruption.
Les implémentations doivent documenter clairement la sémantique et les garanties fournies par chaque méthode d'attente. Lorsqu'une implémentation ne prend pas en charge la suspension des threads d'interruption, elle doit se conformer à la sémantique d'interruption définie dans cette interface.
Étant donné que les interruptions impliquent généralement une annulation et que les vérifications d'interruption sont généralement rarement effectuées, les implémentations peuvent répondre aux interruptions avant le retour de la méthode normale. Cela est vrai même lorsqu'une interruption qui se produit après une autre opération peut libérer le verrou de thread. Les implémentations doivent documenter ce comportement.
À partir de :
1.5
<br>
| |||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
nul |
await () <br> Met le thread actuel dans un état d'attente jusqu'à ce qu'il reçoive un signal ou soit interrompu . |
||||||||||||||||
booléen |
attendre<table style="width: 100%" border="1"><tbody><tr class="TableHeadingColor"><th align="left"><span style="font-size: small"><strong>方法详细信息</strong></span></th></tr></tbody></table>(longtemps, unité TimeUnit) Fait en sorte que le thread actuel soit dans un état d'attente jusqu'à ce qu'il reçoive un signal, soit interrompu ou atteigne le temps d'attente spécifié.
|
||||||||||||||||
long |
awaitNanos(long nanosTimeout) Fait en sorte que le thread actuel reste dans un état d'attente jusqu'à ce qu'il reçoive un signal, soit interrompu ou atteigne le temps d'attente spécifié.
|
||||||||||||||||
void |
attendre sans interruption() span> Fait attendre le thread actuel jusqu'à ce qu'il reçoive le signal. |
||||||||||||||||
booléen |
awaitUntil(Date limite) Fait attendre le thread actuel jusqu'à ce qu'il reçoive un signal, soit interrompu ou atteigne la date limite spécifiée.
|
||||||||||||||||
void |
signal() span> Réveillez un fil de discussion en attente. |
||||||||||||||||
void |
signalAll() span> Réveillez tous les fils de discussion en attente. |
Détails de la méthode |
---|
<br>
void await() throws InterruptedException
造成当前线程在接到信号或被中断之前一直处于等待状态。
与此 Condition
相关的锁以原子方式释放,并且出于线程调度的目的,将禁用当前线程,且在发生以下四种情况之一 以前,当前线程将一直处于休眠状态:
其他某个线程调用此 Condition
的 signal()
方法,并且碰巧将当前线程选为被唤醒的线程;或者
其他某个线程调用此 Condition
的 signalAll()
方法;或者
其他某个线程中断当前线程,且支持中断线程的挂起;或者
发生“虚假唤醒”
在所有情况下,在此方法可以返回当前线程之前,都必须重新获取与此条件有关的锁。在线程返回时,可以保证 它保持此锁。
如果当前线程:
在进入此方法时已经设置了该线程的中断状态;或者
在支持等待和中断线程挂起时,线程被中断,
则抛出 InterruptedException
,并清除当前线程的中断状态。在第一种情况下,没有指定是否在释放锁之前发生中断测试。
实现注意事项
假定调用此方法时,当前线程保持了与此 Condition
有关联的锁。这取决于确定是否为这种情况以及不是时,如何对此作出响应的实现。通常,将抛出一个异常(比如 IllegalMonitorStateException
)并且该实现必须对此进行记录。
与响应某个信号而返回的普通方法相比,实现可能更喜欢响应某个中断。在这种情况下,实现必须确保信号被重定向到另一个等待线程(如果有的话)。
抛出:
InterruptedException
- 如果当前线程被中断(并且支持中断线程挂起)
<br>
void awaitUninterruptibly()
造成当前线程在接到信号之前一直处于等待状态。
与此条件相关的锁以原子方式释放,并且出于线程调度的目的,将禁用当前线程,且在发生以下三种情况之一 以前,当前线程将一直处于休眠状态:
其他某个线程调用此 Condition
的 signal()
方法,并且碰巧将当前线程选为被唤醒的线程;或者
其他某个线程调用此 Condition
的 signalAll()
方法;或者
发生“虚假唤醒”
在所有情况下,在此方法可以返回当前线程之前,都必须重新获取与此条件有关的锁。在线程返回时,可以保证 它保持此锁。
如果在进入此方法时设置了当前线程的中断状态,或者在等待时,线程被中断,那么在接到信号之前,它将继续等待。当最终从此方法返回时,仍然将设置其中断状态。
实现注意事项
假定调用此方法时,当前线程保持了与此 Condition
有关联的锁。这取决于确定是否为这种情况以及不是时,如何对此作出响应的实现。通常,将抛出一个异常(比如 IllegalMonitorStateException
)并且该实现必须对此进行记录。
<br>
long awaitNanos(long nanosTimeout) throws InterruptedException
造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。
与此条件相关的锁以原子方式释放,并且出于线程调度的目的,将禁用当前线程,且在发生以下五种情况之一 以前,当前线程将一直处于休眠状态:
其他某个线程调用此 Condition
的 signal()
方法,并且碰巧将当前线程选为被唤醒的线程;或者
其他某个线程调用此 Condition
的 signalAll()
方法;或者
其他某个线程中断当前线程,且支持中断线程的挂起;或者
已超过指定的等待时间;或者
发生“虚假唤醒”。
在所有情况下,在此方法可以返回当前线程之前,都必须重新获取与此条件有关的锁。在线程返回时,可以保证 它保持此锁。
如果当前线程:
在进入此方法时已经设置了该线程的中断状态;或者
在支持等待和中断线程挂起时,线程被中断,
则抛出 InterruptedException
,并且清除当前线程的已中断状态。在第一种情况下,没有指定是否在释放锁之前发生中断测试。
在返回时,该方法返回了所剩毫微秒数的一个估计值,以等待所提供的 nanosTimeout
值的时间,如果超时,则返回一个小于等于 0 的值。可以用此值来确定在等待返回但某一等待条件仍不具备的情况下,是否要再次等待,以及再次等待的时间。此方法的典型用法采用以下形式:
synchronized boolean aMethod(long timeout, TimeUnit unit) { long nanosTimeout = unit.toNanos(timeout); while (!conditionBeingWaitedFor) { if (nanosTimeout > 0) nanosTimeout = theCondition.awaitNanos(nanosTimeout); else return false; } // ... }
设计注意事项:此方法需要一个 nanosecond 参数,以避免在报告剩余时间时出现截断错误。在发生重新等待时,这种精度损失使得程序员难以确保总的等待时间不少于指定等待时间。
实现注意事项
假定调用此方法时,当前线程保持了与此 Condition
有关联的锁。这取决于确定是否为这种情况以及不是时,如何对此作出响应的实现。通常会抛出一个异常(比如 IllegalMonitorStateException
)并且该实现必须对此进行记录。
与响应某个信号而返回的普通方法相比,或者与指示所使用的指定等待时间相比,实现可能更喜欢响应某个中断。在任意一种情况下,实现必须确保信号被重定向到另一个等待线程(如果有的话)。
参数:
nanosTimeout
- 等待的最长时间,以毫微秒为单位
返回:
nanosTimeout
值减去花费在等待此方法的返回结果的时间的估算。正值可以用作对此方法进行后续调用的参数,来完成等待所需时间结束。小于等于零的值表示没有剩余时间。
抛出:
InterruptedException
- 如果当前线程被中断(并且支持中断线程挂起)
<br>
boolean await(long time, TimeUnit unit) throws InterruptedException
造成当前线程在接到信号、被中断或到达指定等待时间之前一直处于等待状态。此方法在行为上等效于:
awaitNanos(unit.toNanos(time)) > 0
参数:
time
- 最长等待时间
unit
- time
参数的时间单位
返回:
如果在从此方法返回前检测到等待时间超时,则返回 false
,否则返回 true
抛出:
InterruptedException
- 如果当前线程被中断(并且支持中断线程挂起)
<br>
boolean awaitUntil(Date deadline) throws InterruptedException
造成当前线程在接到信号、被中断或到达指定最后期限之前一直处于等待状态。
与此条件相关的锁以原子方式释放,并且出于线程调度的目的,将禁用当前线程,且在发生以下五种情况之一 以前,当前线程将一直处于休眠状态:
其他某个线程调用此 Condition
的 signal()
方法,并且碰巧将当前线程选为被唤醒的线程;或者
其他某个线程调用此 Condition
的 signalAll()
方法;或者
其他某个线程中断当前线程,且支持中断线程的挂起;或者
指定的最后期限到了;或者
发生“虚假唤醒”。
在所有情况下,在此方法可以返回当前线程之前,都必须重新获取与此条件有关的锁。在线程返回时,可以保证 它保持此锁。
如果当前线程:
在进入此方法时已经设置了该线程的中断状态;或者
在支持等待和中断线程挂起时,线程被中断,
则抛出 InterruptedException
,并且清除当前线程的已中断状态。在第一种情况下,没有指定是否在释放锁之前发生中断测试。
返回值指示是否到达最后期限,使用方式如下:
synchronized boolean aMethod(Date deadline) { boolean stillWaiting = true; while (!conditionBeingWaitedFor) { if (stillWaiting) stillWaiting = theCondition.awaitUntil(deadline); else return false; } // ... }
实现注意事项
假定调用此方法时,当前线程保持了与此 Condition
有关联的锁。这取决于确定是否为这种情况以及不是时,如何对此作出响应的实现。通常,将抛出一个异常(比如 IllegalMonitorStateException
)并且该实现必须对此进行记录。
与响应某个信号而返回的普通方法相比,或者与指示是否到达指定最终期限相比,实现可能更喜欢响应某个中断。在任意一种情况下,实现必须确保信号被重定向到另一个等待线程(如果有的话)。
参数:
deadline
- 一直处于等待状态的绝对时间
返回:
如果在返回时已经到达最后期限,则返回 false
,否则返回 true
抛出:
InterruptedException
- 如果当前线程被中断(并且支持中断线程挂起)
<br>
void signal()
唤醒一个等待线程。
如果所有的线程都在等待此条件,则选择其中的一个唤醒。在从 await
返回之前,该线程必须重新获取锁。
<br>
void signalAll()
唤醒所有等待线程。
如果所有的线程都在等待此条件,则唤醒所有线程。在从 await
返回之前,每个线程都必须重新获取锁。
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!