Runnable vs Callable i Java

1. Oversikt

Siden de første dagene av Java har multitrading vært et viktig aspekt av språket. Kjørbar er det viktigste grensesnittet for å representere oppgaver med flere tråder og Kan kalles er en forbedret versjon av Kjørbar som ble lagt til i Java 1.5.

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

2. Utførelsesmekanisme

Begge grensesnittene er designet for å representere en oppgave som kan utføres av flere tråder. Kjørbar oppgaver kan kjøres ved hjelp av Tråd klasse eller ExecutorService mens Callables kan bare kjøres ved hjelp av sistnevnte.

3. Returverdier

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

3.1. Med Kjørbar

De Kjørbar grensesnitt er et funksjonelt grensesnitt og har et enkelt løpe() metode som ikke godtar noen parametere og ikke returnerer noen verdier.

Dette er egnet for situasjoner der vi ikke leter etter et resultat av trådutførelsen, for eksempel innkommende hendelseslogging:

offentlig grensesnitt Runnable {public void run (); }

La oss forstå dette med et eksempel:

offentlig klasse EventLoggingTask implementerer 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 med ExecutorService:

public void executeTask () {executorService = Executors.newSingleThreadExecutor (); Fremtidig fremtid = executorService.submit (ny EventLoggingTask ()); executorService.shutdown (); }

I dette tilfellet Framtid objektet vil ikke ha noen verdi.

3.2. Med Kan kalles

De Kan kalles grensesnitt er et generisk grensesnitt som inneholder en enkelt anrop() metode - som returnerer en generell verdi V:

offentlig grensesnitt Callable {V call () kaster Unntak; }

La oss ta en titt på beregningen av et talls faktor:

offentlig klasse FactorialTask ​​implementerer Callable {int nummer; // standard constructors public Integer call () kaster InvalidParamaterException {int fact = 1; // ... for (int count = number; count> 1; count -) {fact = fact * count; } returnere faktum; }}

Resultatet av anrop() metoden returneres innen en Framtid gjenstand:

@Test offentlig ugyldig nårTaskSubitted_ThenFutureResultObtained () {FactorialTask ​​task = new FactorialTask ​​(5); Fremtidig fremtid = executorService.submit (oppgave); assertEquals (120, future.get (). intValue ()); }

4. Unntakshåndtering

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

4.1. Med Kjørbar

Siden metodesignaturen ikke har "kast" -klausulen spesifisert,det er ingen måte å forplante ytterligere kontrollerte unntak.

4.2. Med Kan kalles

Ringbar samtale () metoden inneholder “kast Unntak" klausul slik at vi enkelt kan videreformidle sjekket unntak videre:

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

I tilfelle du kjører en Kan kalles med en ExecutorService, unntakene er samlet i Framtid objekt, som kan kontrolleres ved å ringe til Future.get () metode. Dette vil kaste en Utførelse unntak - som pakker det opprinnelige unntaket:

@Test (forventet = ExecutionException.class) offentlig ugyldig nårException_ThenCallableThrowsIt () {FactorialCallableTask oppgave = ny FactorialCallableTask (-5); Fremtidig fremtid = executorService.submit (oppgave); Heltalsresultat = future.get (). IntValue (); }

I testen ovenfor, den Utførelse Unntak blir kastet når vi passerer et ugyldig nummer. Vi kan ringe getCause () metoden på dette unntaksobjektet for å få det opprinnelige kontrollerte unntaket.

Hvis vi ikke ringer til få() Metode av Framtid klasse - så unntaket kastet av anrop() metoden vil ikke bli rapportert tilbake, og oppgaven vil fortsatt være merket som fullført:

@Test offentlig ugyldig nårException_ThenCallableDoesntThrowsItIfGetIsNotCalled () {FactorialCallableTask oppgave = ny FactorialCallableTask (-5); Fremtidig fremtid = executorService.submit (oppgave); assertEquals (false, future.isDone ()); }

Ovennevnte test vil bestå vellykket, selv om vi har kastet et unntak for de negative verdiene til parameteren FaktorKallbar oppgave.

5. Konklusjon

I denne artikkelen har vi utforsket forskjellene mellom Kjørbar og Kan kalles grensesnitt.

Som alltid er den fullstendige koden for denne artikkelen tilgjengelig på GitHub.


$config[zx-auto] not found$config[zx-overlay] not found