Runnable vs. Callable I Java

Oversikt

siden Begynnelsen Av Java har multithreading vært et viktig aspekt av språket. Runnable er kjernen grensesnittet gitt for å representere multi-threaded oppgaver Og Callable er en forbedret versjon Av Runnable som ble lagt I Java 1.5.

i denne artikkelen vil vi utforske forskjellene og applikasjonene til begge grensesnittene.

Utførelsesmekanisme

begge grensesnittene er utformet for å representere en oppgave som kan utføres av flere tråder. Runnable oppgaver kan kjøres ved Hjelp Av Tråden klasse eller ExecutorService mens Callables kan kjøres bare ved hjelp av sistnevnte.

Returverdier

La oss se nærmere på hvordan disse grensesnittene håndterer returverdier.

3.1. Med Runnable

Er Runnable-grensesnittet et funksjonelt grensesnitt og har en enkelt run () – metode som ikke godtar noen parametere og returnerer ingen verdier.

dette er egnet for situasjoner der vi ikke ser etter et resultat av trådutførelsen, for eksempel innkommende hendelser logging:

public interface Runnable { public void run();}

La oss forstå dette med et eksempel:

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

i dette eksemplet vil tråden bare lese en melding fra køen og logge den i en loggfil. Det er ingen verdi returnert fra oppgaven; oppgaven kan startes ved Hjelp ExecutorService:

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

I Dette tilfellet Vil Det Fremtidige objektet ikke ha noen verdi.

3.2. Med Callable

Det Callable grensesnittet er et generisk grensesnitt som inneholder en enkelt samtale() metode – som returnerer en generisk verdi V:

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

La oss ta en titt på å beregne faktorialet til et tall:

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; }}

resultatet av call () – metoden returneres i Et Fremtidig objekt:

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

Unntakshåndtering

La oss se hvor egnet de er for unntakshåndtering.

4.1. Med Runnable

Siden metodesignaturen ikke har» kaster » – klausulen spesifisert, er det ingen måte å forplante ytterligere kontrollerte unntak.

4.2. Med Callable

Callable call() metoden inneholder» kaster Unntak » klausul slik at vi enkelt kan forplante sjekket unntak videre:

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

ved kjøring Av En Callable ved hjelp av En ExecutorService, samles unntakene I Det Fremtidige objektet, som kan kontrolleres ved å ringe Til Fremtiden.få () metode. Dette vil kaste En ExecutionException – som bryter det opprinnelige unntaket:

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

I ovennevnte test blir Utførelsenunntak blir kastet når vi passerer et ugyldig nummer. Vi kan ringe getCause () – metoden på dette unntaksobjektet for å få det opprinnelige sjekket unntaket.

hvis vi ikke ringer til get () – metoden For Fremtidig klasse-vil unntaket kastet av call () – metoden ikke bli rapportert tilbake, og oppgaven vil fortsatt bli merket som fullført:

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

ovennevnte test vil passere vellykket selv om vi har kastet et unntak for de negative verdiene til parameteren Til FactorialCallableTask.

Konklusjon

I denne artikkelen har vi utforsket forskjellene Mellom runnable og Callable grensesnitt.

som alltid er den komplette koden for denne artikkelen tilgjengelig over På GitHub.

Kom I Gang Med Spring 5 og Spring Boot 2, gjennom Learn Spring course:

>> SJEKK UT KURSET

Legg igjen en kommentar

Din e-postadresse vil ikke bli publisert.

Previous post Nitril
Next post Julian Morris På ‘New Girl’ = Beste Ideen Noensinne