Pourquoi Java Avenir.get(délai d'expiration) ne sont Pas Fiables?
Avenir.get(délai d'expiration) ne sont pas fiables jeter le TimeoutException après le délai d'attente. Est-ce un comportement normal, ou puis-je faire quelque chose pour le rendre plus fiable? Ce test échoue sur ma machine. Cependant, si je dors à 3000 au lieu de 2000, ça va passer.
public class FutureTimeoutTest {
@Test
public void test() throws
ExecutionException,
InterruptedException {
ExecutorService exec = Executors.newSingleThreadExecutor();
final Callable call = new Callable() {
@Override
public Object call() throws Exception {
try {
Thread.sleep(2000);
} catch (InterruptedException ex) {
ex.printStackTrace();
}
return 0;
}
};
final Future future = exec.submit(call);
try {
future.get(1000, TimeUnit.MILLISECONDS);
fail("expected TimeoutException");
} catch (TimeoutException ignore) {
}
}
}
- Intéressant. Varie-t-elle par la plate-forme? Il pourrait être un bug dans la JVM ou de l'OS.
- Je ne suis pas sûr que ce serait vraiment compter comme un bug en soi. Il y a certainement des non-déterminisme dans combien de temps sera passé entre le point de départ que l'autre thread et même de commencer à attendre pour l'Avenir pour compléter. Oui, 1 seconde semble un peu beaucoup, mais je ne vois rien dans les docs qui rendent difficile les garanties sur les délais.
- Je ne l'ai essayé sur Windows XP. Je suis d'accord qu'il pourrait être non-déterminisme, cependant il n'y a pas beaucoup qui se passe dans cet exemple. Mon cas réels a plusieurs threads et il y a blocage au sein JNI sur les réponses de réseau. Je peux comprendre une certaine variabilité dans le timeout dans ce cas, mais ici?
- Ce JVM/JDK/IDE/TestFramework utilisez-vous? Cela fonctionne très bien dans le Soleil JDK6 + jUnit4 + Netbeans.
- souligne qu'il pourrait être un fil de contention question: qu'advient-il si vous changez le test à exécuter dans un seul thread à l'aide d'un
FutureTask
? - Cela fonctionne très bien sur ma machine, le Soleil JDK6, Windows Server 2008 R2.
Vous devez vous connecter pour publier un commentaire.
Il n'y a aucune raison pour que le test à passer. Étant donné que de vous présenter la tâche pour l'exécution et ensuite attendre à son achèvement, tout le temps pouvait passer avant votre attente sur
Future#get()
commence, permettant ainsi à la tâche de beaucoup de temps pour épuiser la durée du sommeil et complète.Dans votre cas, on peut supposer que le thread en cours d'exécution dans le
Executor
obtient le focus pendant que votre thread principal cours d'exécution à traverstest()
est en attente, en dépit d'être dans un état exécutable. Comme pour la différence observée entre le décrochage de l'soumis à la tâche pour les deux et trois secondes, j'attends de vous peut se trouver des situations où même les trois secondes est insuffisant, selon ce que les autres processus sont occupés à faire sur votre ordinateur.@seh est droit.
Vous vous attendez à ce qui est communément appelé "temps réel" comportement à partir de Java. Cela ne peut pas être réalisé de manière fiable à moins de l'utiliser en temps réel les bibliothèques, dans un temps réel capable de Java distribution en cours d'exécution sur un système d'exploitation temps réel.
Juste pour illustrer, le fil de Java mise en œuvre dans de modernes machines virtuelles comme HotSpot s'appuie sur le système d'exploitation hôte du thread natif planificateur de décider ce que les threads de s'exécuter lorsque. À moins que le planificateur de threads est précisément au courant en temps réel des délais et des choses, il est susceptible de prendre un "ensemble du système" vue au moment de décider quels threads de s'exécuter lorsque. Si le système est chargé, chaque thread peut ne pas se dérouler secondes ... ou plus ... une fois que les conditions qui l'a empêché l'exécution (par exemple, en attente d'un événement timer) ont passé.
Puis il y a le problème que le Java GC peut entraîner de tous les autres threads d'un bloc.
Si vous avez vraiment besoin d'un comportement en temps réel à partir de Java, il est disponible. Par exemple:
Cependant, vous devez vous attendre pour changer vos applications d'utiliser des Api différentes pour vous donner en temps réel le comportement.
Que j'ai à dire, je pense que les deux autres réponses ont actuellement trop faible opinion de la Java de la simultanéité des classes. Ils ne vont pas vous donner une précision à la milliseconde (ce "réel" des applications en temps réel attendre), mais ils le font très bien d'habitude. J'ai écrit l'échelle commerciale des services à l'aide de contrats à Terme et les Exécuteurs testamentaires et normalement, ils ont travaillé dans les 10 millisecondes de l'époque prévue, même sous charge.
J'ai fait ce test à la fois sur MacOS 10.6 avec la version 1.6 de Java et WinXP w/Java 1.6.0_22, et deux d'entre eux fonctionnent comme prévu.
J'ai modifié le code comme suit pour tester la précision:
Sous XP cela s'imprime "timed out après 1.002598934 secondes" et dans MacOS X, il imprime "timed out après 1.003158 secondes".
Si le posteur d'origine permettrait de décrire leur système d'exploitation et la version de JDK, on pourrait peut-être déterminer si c'est un bogue particulier.