Implementering af en kørbar vs udvidelse af en tråd
1. Introduktion
”Skal jeg implementere en Kan køres eller udvide Tråd klasse ”? er et ret almindeligt spørgsmål.
I denne artikel vil vi se, hvilken tilgang der giver mere mening i praksis, og hvorfor.
2. Brug Tråd
Lad os først definere en SimpleTråd klasse, der strækker sig Tråd:
offentlig klasse SimpleThread udvider tråd {privat strengbesked; // standard logger, constructor @ Override public void run () {log.info (meddelelse); }}
Lad os også se, hvordan vi kan køre en tråd af denne type:
@Test offentlig ugyldighed givenAThread_whenRunIt_thenResult () kaster undtagelse {thread thread = new SimpleThread ("SimpleThread udført ved hjælp af thread"); thread.start (); thread.join (); }
Vi kan også bruge en ExecutorService at udføre tråden:
@Test offentlig ugyldighed givenAThread_whenSubmitToES_thenResult () kaster undtagelse {executorService.submit (ny SimpleThread ("SimpleThread udført ved hjælp af ExecutorService")). Get (); }
Det er ret meget kode til at køre en enkelt logoperation i en separat tråd.
Bemærk også, at SimpleTråd kan ikke udvide nogen anden klasse, da Java ikke understøtter flere arv.
3. Implementering af a Kan køres
Lad os nu oprette en simpel opgave, der implementerer java.lang.Køres grænseflade:
klasse SimpleRunnable implementerer Runnable {private String message; // standard logger, constructor @ Override public void run () {log.info (meddelelse); }}
Ovenstående SimpleRunnable er bare en opgave, som vi vil køre i en separat tråd.
Der er forskellige tilgange, vi kan bruge til at køre det; en af dem er at bruge Tråd klasse:
@Test offentlig ugyldighed givenRunnable_whenRunIt_thenResult () kaster undtagelse {Thread thread = new Thread (new SimpleRunnable ("SimpleRunnable executed using Thread")); thread.start (); thread.join (); }
Vi kan endda bruge en ExecutorService:
@Test offentlig ugyldighed givetARunnable_whenSubmitToES_thenResult () kaster Undtagelse {executorService.submit (ny SimpleRunnable ("SimpleRunnable udført ved hjælp af ExecutorService")). Get (); }
Vi kan læse mere om ExecutorService herinde.
Da vi nu implementerer en grænseflade, kan vi udvide en anden basisklasse, hvis vi har brug for det.
Startende med Java 8 behandles enhver grænseflade, der udsætter en enkelt abstrakt metode, som en funktionel grænseflade, hvilket gør det til et gyldigt lambda-ekspressionsmål.
Vi kan omskrive ovenstående Kan køres kode ved hjælp af et lambda-udtryk:
@Test offentlig ugyldighed givetARunnableLambda_whenSubmitToES_thenResult () kaster Undtagelse {executorService.submit (() -> log.info ("Lambda kørbar udført!")); }
4. Kan køres eller Tråd?
Kort sagt, vi opfordrer generelt brugen af Kan køres over Tråd:
- Når du udvider Tråd klasse overstyrer vi ikke nogen af dens metoder. I stedet tilsidesætter vi metoden til Kan køres (hvilken Tråd tilfældigvis implementerer). Dette er en klar overtrædelse af IS-A Tråd princip
- Oprettelse af en implementering af Kan køres og videregiver det til Tråd klasse bruger komposition og ikke arv - hvilket er mere fleksibelt
- Efter udvidelse af Tråd klasse, kan vi ikke udvide nogen anden klasse
- Fra Java 8 og frem, Runnables kan repræsenteres som lambda-udtryk
5. Konklusion
I denne hurtige vejledning så vi, hvordan implementering Kan køres er typisk en bedre tilgang end at udvide Tråd klasse.
Koden til dette indlæg kan findes på GitHub.