web-dev-qa-db-fra.com

Comment utiliser Callable avec le type de retour nul?

Je travaille sur un projet dans lequel j'ai plusieurs interfaces et deux classes d'implémentations qui doivent implémenter ces deux interfaces.

Supposons que ma première interface soit -

public Interface interfaceA {
    public void abc() throws Exception;
}

Et sa mise en œuvre est -

public class TestA implements interfaceA {

// abc method
}

Je l'appelle comme ça -

TestA testA = new TestA();
testA.abc();

Maintenant ma deuxième interface est -

public Interface interfaceB {
    public void xyz() throws Exception;
}

Et sa mise en œuvre est -

public class TestB implements interfaceB {

// xyz method   
}

Je l'appelle comme ça -

TestB testB = new TestB();
testB.xyz();

Énoncé du problème: -

Ma question est la suivante: y at-il un moyen, je peux exécuter ces deux classes d'implémentation en parallèle? Je ne veux pas l'exécuter en séquentiel.

Ce qui signifie, je veux exécuter TestA et TestB implémentation en parallèle? Est-ce possible?

Je pensais utiliser Callable ici, mais je ne savais pas comment utiliser Callable avec un type de retour vide ici -

Utilisons la classe TestB comme exemple:

public interface interfaceB {
    public void xyz() throws Exception;
}

public class TestB implements interfaceB, Callable<?>{

    @Override
    public void xyz() throws Exception
    {
        //do something

    }

    @Override
    public void call() throws Exception
    {
        xyz();
    }
}

Le code ci-dessus donne une erreur de compilation.

PDATE: -

Il semble que beaucoup de gens suggèrent d'utiliser Runnable au lieu de callable. Mais je ne sais pas comment utiliser Runnable ici pour pouvoir exécuter TestA and TestB en parallèle.

55
AKIWEB

Vous pouvez utiliser Java.lang.Thread pour une exécution parallèle. Cependant, dans la plupart des cas, il est plus facile d'utiliser un Java.util.concurrent.ExecutorService. Ce dernier fournit une méthode pour soumettre un Callable et renvoie un Future pour obtenir le résultat plus tard (ou attendre la fin).

Si testA.abc () et testB.xyz () doivent être exécutés en parallèle, vous utilisez ExecutorService pour exécuter l'ancien dans un environnement séparé. thread alors que ce dernier est exécuté dans le thread d'origine. Ensuite, vous attendez la fin de la précédente pour la synchronisation.

ExecutorService executor = ... // e.g. Executors.newFixedThreadPool(4);

Future<Void> future = executor.submit(new Callable<Void>() {
    public Void call() throws Exception {
        testA.abc();
        return null;
    }
});
testB.xyz();
future.get(); // wait for completion of testA.abc()
73
nosid

Pourquoi auriez-vous besoin d'un vide pour exécuter quelque chose en parallèle? D'une part, si vous n'avez pas besoin de la valeur de retour, vous pouvez simplement renvoyer null.

Pour faire quelque chose de parallèle, vous devez utiliser le threading/ordonnancement. Je recommanderais personnellement d'éviter Callables et d'utiliser plutôt Runnables (et bon, aucune valeur de retour).

5
Rogue

Une version plus courte:

ExecutorService executor = ... // e.g. Executors.newFixedThreadPool(4);
Future<?> future = executor.submit(() -> testA.abc());
testB.xyz();
future.get(); // wait for completion of testA.abc()

A noter que le fait d'exécuter quelque chose en parallèle sans rien retourner ne peut être le signe d'un mauvais modèle :)

De plus, si vous êtes dans un environnement Spring, vous pouvez utiliser: https://spring.io/guides/gs/async-method/

1
AddJ