Runnable vs.Callable in Java

áttekintés

mivel az első napokban a Java, többszálú volt a fő szempont a nyelv. A Runnable a többszálú feladatok ábrázolására szolgáló alapvető felület, a Callable pedig a Runnable továbbfejlesztett változata, amelyet a Java 1.5-ben adtak hozzá.

ebben a cikkben megvizsgáljuk a két interfész különbségeit és alkalmazásait.

végrehajtási mechanizmus

mindkét interfész úgy van kialakítva, hogy egy több szál által végrehajtható feladatot ábrázoljon. A futtatható feladatok futtathatók a Thread osztály vagy az ExecutorService használatával, míg a Callables csak az utóbbi használatával futtatható.

visszatérési értékek

vessünk egy mélyebb pillantást arra, hogy ezek az interfészek hogyan kezelik a visszatérési értékeket.

3.1. Runnable

esetén a Runnable interfész egy funkcionális interfész, és egyetlen run () metódussal rendelkezik, amely nem fogad el semmilyen paramétert és nem ad vissza semmilyen értéket.

ez alkalmas olyan helyzetekre, amikor nem a szál végrehajtásának eredményét keressük, például bejövő események naplózása:

public interface Runnable { public void run();}

értsük meg ezt egy példával:

public class EventLoggingTask implements Runnable{ private Logger logger = LoggerFactory.getLogger(EventLoggingTask.class); @Override public void run() { logger.info("Message"); }}

ebben a példában a szál csak kiolvas egy üzenetet a sorból, majd naplófájlba rögzíti. A feladat nem ad vissza értéket; a feladat elindítható az ExecutorService használatával:

public void executeTask() { executorService = Executors.newSingleThreadExecutor(); Future future = executorService.submit(new EventLoggingTask()); executorService.shutdown();}

ebben az esetben a jövőbeli objektumnak nincs értéke.

3.2. Val vel hívható

A hívható felület egy általános felület, amely egyetlen hívást () metódust tartalmaz-amely általános értéket ad vissza V:

public interface Callable<V> { V call() throws Exception;}

vessünk egy pillantást egy szám faktoriálisának kiszámítására:

public class FactorialTask implements Callable<Integer> { int number; // standard constructors public Integer call() throws InvalidParamaterException { int fact = 1; // ... for(int count = number; count > 1; count--) { fact = fact * count; } return fact; }}

a call() metódus eredménye egy jövőbeli objektumon belül kerül visszaadásra:

@Testpublic void whenTaskSubmitted_ThenFutureResultObtained(){ FactorialTask task = new FactorialTask(5); Future<Integer> future = executorService.submit(task); assertEquals(120, future.get().intValue());}

kivételkezelés

lássuk, mennyire alkalmasak a kivételek kezelésére.

4.1. Futtatható

mivel a metódus aláírása nem rendelkezik a” dobások ” záradékkal, nincs mód további ellenőrzött kivételek terjesztésére.

4.2. A Callable

Callable ‘s call () metódus” dob kivétel ” záradékot tartalmaz, így könnyen tovább tudjuk terjeszteni az ellenőrzött kivételeket:

public class FactorialTask implements Callable<Integer> { // ... public Integer call() throws InvalidParamaterException { if(number < 0) { throw new InvalidParamaterException("Number should be positive"); } // ... }}

abban az esetben fut egy hívható egy ExecutorService, a kivételek gyűjtik a jövőben objektum, amely ellenőrizhető, hogy egy hívást a jövőben.get () módszer. Ez dob egy ExecutionException – amely becsomagolja az eredeti kivételt:

@Test(expected = ExecutionException.class)public void whenException_ThenCallableThrowsIt() { FactorialCallableTask task = new FactorialCallableTask(-5); Future<Integer> future = executorService.submit(task); Integer result = future.get().intValue();}

a fenti tesztben az ExecutionException dobásra kerül, mivel érvénytelen számot adunk át. Hívhatjuk a getcause () metódust ezen a kivétel objektumon, hogy megkapjuk az eredeti ellenőrzött kivételt.

ha nem kezdeményezzük a hívást a Get () metódusra a Future class-ban, akkor a call () metódus által dobott kivétel nem kerül jelentésre, és a feladat továbbra is befejezettként lesz megjelölve:

@Testpublic void whenException_ThenCallableDoesntThrowsItIfGetIsNotCalled(){ FactorialCallableTask task = new FactorialCallableTask(-5); Future<Integer> future = executorService.submit(task); assertEquals(false, future.isDone());}

a fenti teszt sikeres lesz, annak ellenére, hogy kivételt dobtunk a paraméter negatív értékeire a FactorialCallableTask számára.

következtetés

ebben a cikkben a futtatható és a hívható interfészek közötti különbségeket tártuk fel.

mint mindig, a cikk teljes kódja elérhető a Githubon.

kezdje el a Spring 5 és a Spring Boot 2 használatával a Learn Spring tanfolyamon keresztül:

>> nézze meg a tanfolyamot

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.

Previous post Nitril
Next post Julian Morris on ‘New Girl’ = legjobb ötlet valaha