Blockingqueue og Dens Implementasjoner
Grunnleggende BlockingQueue-implementasjoner
Vi vil ikke gå gjennom hver implementasjon i detalj, da det ville tatt mye tid, og det er lite sannsynlig at du vil trenge dem alle. Jeg vil forklare de generelle konseptene og hvilke konstruktører de har.
Eksempel fra virkeligheten
Tenk deg en fabrikk der én tråd, produsenten, lager deler, og en annen tråd, konsumenten, bearbeider dem. Produsenten legger delene i en kø, mens konsumenten henter og bearbeider dem fra køen. Hvis køen går tom for deler, venter konsumenten på at produsenten skal legge til flere. Omvendt, hvis køen er full, venter produsenten på at konsumenten skal frigjøre plass.
Litt lenger ned vil vi implementere denne oppgaven i kode.
Forskjeller fra andre samlingstyper
BlockingQueue gir automatisk synkronisering, og håndterer trådadgang til køen uten behov for manuell synkronisering. Den støtter også blokkerende operasjoner for å legge til og hente elementer, en funksjon som ikke finnes i andre samlinger som ArrayList eller LinkedList.
BlockingQueue-implementasjoner
ArrayBlockingQueue: En størrelsesbegrenset kø som bruker et array for å lagre elementer.
Main.java
123456789// Constructor with fixed capacity BlockingQueue<String> queue1 = new ArrayBlockingQueue<>(5); // Constructor with fixed capacity and fair access BlockingQueue<String> queue2 = new ArrayBlockingQueue<>(5, true); // Constructor with fixed capacity and initial collection of elements Collection<String> initialElements = java.util.Arrays.asList("One", "Two", "Three"); BlockingQueue<String> queue3 = new ArrayBlockingQueue<>(5, false, initialElements);
true-parameteren aktiverer en rettferdig tilgangspolicy ved å gi en FIFO-rekkefølge for trådadgang.
LinkedBlockingQueueue: En kø basert på lenkede noder som kan være begrenset eller ubegrenset.
Main.java
123456789// Constructor without capacity bounds BlockingQueue<String> queue1 = new LinkedBlockingQueue<>(); // Constructor with fixed capacity BlockingQueue<String> queue2 = new LinkedBlockingQueue<>(5); // Constructor with initial collection of elements Collection<String> initialElements = java.util.Arrays.asList("One", "Two", "Three"); BlockingQueue<String> queue3 = new LinkedBlockingQueue<>(initialElements);
PriorityBlockingQueue: En ubegrenset prioritert kø der elementer hentes ut i henhold til deres naturlige rekkefølge eller som spesifisert av en komparator.
Main.java
12345678910111213// Constructor without initial capacity (default is 11) BlockingQueue<Integer> queue1 = new PriorityBlockingQueue<>(); // Constructor with initial capacity BlockingQueue<Integer> queue2 = new PriorityBlockingQueue<>(5); // Constructor with initial capacity and comparator Comparator<Integer> comparator = Integer::compareTo; BlockingQueue<Integer> queue3 = new PriorityBlockingQueue<>(5, comparator); // Constructor with initial collection of elements Collection<Integer> initialElements = java.util.Arrays.asList(1, 3, 2); BlockingQueue<Integer> queue4 = new PriorityBlockingQueue<>(initialElements)
DelayQueue: En forsinket kø hvor elementer kun kan hentes etter at deres forsinkelse har utløpt.
DelayedElement.java
DelayQueueConstructors.java
123456789101112131415161718class DelayedElement implements Delayed { private final long expirationTime; // The time when the element will be available public DelayedElement(long delay, TimeUnit unit) { this.expirationTime = System.currentTimeMillis() + unit.toMillis(delay); } @Override public long getDelay(TimeUnit unit) { long delay = expirationTime - System.currentTimeMillis(); // Calculate the remaining delay return unit.convert(delay, TimeUnit.MILLISECONDS); // Convert the delay to the specified time unit } @Override public int compareTo(Delayed o) { return Long.compare(this.expirationTime, ((DelayedElement) o).expirationTime); } }
Denne koden demonstrerer bruken av DelayedElement-klassen, som implementerer Delayed-interface, og forsinket kø (DelayQueue) i Java. DelayedElement-klassen definerer en getDelay-metode for å beregne gjenværende forsinkelsestid og en compareTo-metode for å sammenligne objekter basert på utløpstid for forsinkelse.
main-metoden oppretter to køer: queue1, en tom forsinket kø, og queue2, en kø initialisert med elementer som har en forsinkelse på 5 og 1 sekund, henholdsvis.
Elementene i DelayQueueue blir tilgjengelige for henting etter at den angitte forsinkelsestiden har utløpt.
SynchronousQueueue: En kø uten kapasitet, der hver innsettingsoperasjon må vente på den tilsvarende uttaksoperasjonen og omvendt.
Main.java
12345// Constructor without fair access BlockingQueue<String> queue1 = new SynchronousQueue<>(); // Constructor with fair access BlockingQueue<String> queue2 = new SynchronousQueue<>(true);
Hovedmetodene til BlockingQueue:
Legge til elementer:
Metoden void put(E e) setter inn et element i køen, og blokkerer tråden hvis køen er full. Alternativt forsøker metoden boolean offer(E e, long timeout, TimeUnit unit) å legge til et element i køen, og venter i angitt tid hvis køen er full.
Main.java
1234567891011121314151617public class BlockingQueueExample { public static void main(String[] args) { BlockingQueue<String> queue = new ArrayBlockingQueue<>(2); try { queue.put("Element 1"); // Insert the first element, no blocking. queue.put("Element 2"); // Insert the second element, no blocking. // Try to add the third element with a 2-second timeout. // Since the queue is full, it will wait for 2 seconds. boolean success = queue.offer("Element 3", 2, TimeUnit.SECONDS); } catch (InterruptedException e) { e.printStackTrace(); } } }
Dette eksemplet viser innsetting av to elementer i en BlockingQueue uten blokkering, etterfulgt av et forsøk på å legge til et tredje element med en 2-sekunders tidsavbrudd ved bruk av offer()-metoden, som vil vente dersom køen er full.
Henting av element:
Metoden E take() henter og returnerer et element fra køen, og blokkerer tråden dersom køen er tom. Alternativt forsøker metoden E poll(long timeout, TimeUnit unit) å hente et element fra køen, og venter i angitt tid dersom køen er tom.
Main.java
1234567891011121314151617181920212223public class BlockingQueueRetrievalExample { public static void main(String[] args) { BlockingQueue<String> queue = new ArrayBlockingQueue<>(2); try { // Adding elements to the queue queue.put("Element 1"); queue.put("Element 2"); // Retrieve and remove the first element, no blocking since the queue is not empty String item1 = queue.take(); // Returns "Element 1" // Attempt to retrieve and remove the next element with a 2-second timeout String item2 = queue.poll(2, TimeUnit.SECONDS); // Returns "Element 2" // Attempt to retrieve an element when the queue is empty, this will block for 2 seconds String item3 = queue.poll(2, TimeUnit.SECONDS); // Returns `null` after timeout } catch (InterruptedException e) { e.printStackTrace(); } } }
Denne koden legger til to elementer i en BlockingQueue, henter ut og fjerner det første elementet umiddelbart, forsøker å hente ut neste element med en 2-sekunders tidsavbrudd, og prøver til slutt å hente ut et element fra en tom kø, noe som resulterer i null etter tidsavbruddet.
Kontrollere og fjerne elementer:
Metoden boolean remove(Object o) fjerner det spesifiserte elementet fra køen dersom det er til stede. På den annen side kontrollerer metoden boolean contains(Object o) om det spesifiserte elementet finnes i køen uten å fjerne det.
Main.java
1234567891011121314151617181920212223242526public class BlockingQueueCheckRemoveExample { public static void main(String[] args) { BlockingQueue<String> queue = new ArrayBlockingQueue<>(2); try { // Adding elements to the queue queue.put("Element 1"); queue.put("Element 2"); // Check if "Element 1" is in the queue, should return `true` boolean containsElement1 = queue.contains("Element 1"); // true // Remove "Element 1" from the queue, should return `true` boolean removedElement1 = queue.remove("Element 1"); // true // Check if "Element 1" is still in the queue, should return `false` boolean containsElement1AfterRemoval = queue.contains("Element 1"); // false // Try to remove an element that is not in the queue, should return `false` boolean removedElement3 = queue.remove("Element 3"); // false } catch (InterruptedException e) { e.printStackTrace(); } } }
Denne koden legger til to elementer i en BlockingQueue, sjekker om "Element 1" er til stede, fjerner det, sjekker igjen for å bekrefte at det er fjernet, og forsøker deretter å fjerne et ikke-eksisterende element.
Spørring om køens tilstand:
Metoden int size() returnerer antall elementer som for øyeblikket er i køen. For å avgjøre om køen er tom, kan du bruke metoden boolean isEmpty(), som sjekker om køen ikke inneholder noen elementer. For køer med fast kapasitet gir metoden int remainingCapacity() antall gjenværende ledige plasser i køen.
Main.java
123456789101112131415161718192021222324252627282930public class BlockingQueueCapacityExample { public static void main(String[] args) { BlockingQueue<String> queue = new ArrayBlockingQueue<>(3); try { // Adding elements to the queue queue.put("Element 1"); queue.put("Element 2"); // Get the number of elements in the queue int currentSize = queue.size(); // 2 // Check if the queue is empty boolean isQueueEmpty = queue.isEmpty(); // false // Get the remaining capacity in the queue int remainingSpace = queue.remainingCapacity(); // 1 // Add another element to fill the queue queue.put("Element 3"); // Check the size and remaining capacity after adding the third element currentSize = queue.size(); // 3 remainingSpace = queue.remainingCapacity(); // 0 } catch (InterruptedException e) { e.printStackTrace(); } } }
Denne koden legger til elementer i en BlockingQueue, sjekker nåværende størrelse, verifiserer om køen er tom, og fastslår gjenværende kapasitet, deretter oppdateres disse verdiene etter at køen er fylt helt opp.
Realisere et virkelighetsnært eksempel i kode
😭 Begrensninger
En sentral begrensning er ytelse: på grunn av låseoperasjoner kan ytelsen reduseres sammenlignet med ikke-synkroniserte samlinger. I tillegg kan ressurser bli et problem ettersom store køer krever mer minne og prosessor-tid for å håndtere låser og synkroniseringsprosesser.
💪 Fordeler
På den positive siden er systemet trygt i flertrådsmiljø, og gir sikker kommunikasjon mellom tråder uten behov for manuell synkroniseringshåndtering. Det forenkler også koden ved å unngå komplekse synkroniserings- og blokkeringskonstruksjoner. Videre gir fleksibiliteten til ulike BlockingQueue-implementasjoner mulighet for tilpasning til ulike bruksscenarier.
1. Hva er en BlockingQueue i Java?
2. Hva er hovedmetodene i BlockingQueue som blokkerer en tråd?
3. Hva er BlockingQueue nyttig for i flertrådede applikasjoner?
Takk for tilbakemeldingene dine!
Spør AI
Spør AI
Spør om hva du vil, eller prøv ett av de foreslåtte spørsmålene for å starte chatten vår
Awesome!
Completion rate improved to 3.33
Blockingqueue og Dens Implementasjoner
Sveip for å vise menyen
Grunnleggende BlockingQueue-implementasjoner
Vi vil ikke gå gjennom hver implementasjon i detalj, da det ville tatt mye tid, og det er lite sannsynlig at du vil trenge dem alle. Jeg vil forklare de generelle konseptene og hvilke konstruktører de har.
Eksempel fra virkeligheten
Tenk deg en fabrikk der én tråd, produsenten, lager deler, og en annen tråd, konsumenten, bearbeider dem. Produsenten legger delene i en kø, mens konsumenten henter og bearbeider dem fra køen. Hvis køen går tom for deler, venter konsumenten på at produsenten skal legge til flere. Omvendt, hvis køen er full, venter produsenten på at konsumenten skal frigjøre plass.
Litt lenger ned vil vi implementere denne oppgaven i kode.
Forskjeller fra andre samlingstyper
BlockingQueue gir automatisk synkronisering, og håndterer trådadgang til køen uten behov for manuell synkronisering. Den støtter også blokkerende operasjoner for å legge til og hente elementer, en funksjon som ikke finnes i andre samlinger som ArrayList eller LinkedList.
BlockingQueue-implementasjoner
ArrayBlockingQueue: En størrelsesbegrenset kø som bruker et array for å lagre elementer.
Main.java
123456789// Constructor with fixed capacity BlockingQueue<String> queue1 = new ArrayBlockingQueue<>(5); // Constructor with fixed capacity and fair access BlockingQueue<String> queue2 = new ArrayBlockingQueue<>(5, true); // Constructor with fixed capacity and initial collection of elements Collection<String> initialElements = java.util.Arrays.asList("One", "Two", "Three"); BlockingQueue<String> queue3 = new ArrayBlockingQueue<>(5, false, initialElements);
true-parameteren aktiverer en rettferdig tilgangspolicy ved å gi en FIFO-rekkefølge for trådadgang.
LinkedBlockingQueueue: En kø basert på lenkede noder som kan være begrenset eller ubegrenset.
Main.java
123456789// Constructor without capacity bounds BlockingQueue<String> queue1 = new LinkedBlockingQueue<>(); // Constructor with fixed capacity BlockingQueue<String> queue2 = new LinkedBlockingQueue<>(5); // Constructor with initial collection of elements Collection<String> initialElements = java.util.Arrays.asList("One", "Two", "Three"); BlockingQueue<String> queue3 = new LinkedBlockingQueue<>(initialElements);
PriorityBlockingQueue: En ubegrenset prioritert kø der elementer hentes ut i henhold til deres naturlige rekkefølge eller som spesifisert av en komparator.
Main.java
12345678910111213// Constructor without initial capacity (default is 11) BlockingQueue<Integer> queue1 = new PriorityBlockingQueue<>(); // Constructor with initial capacity BlockingQueue<Integer> queue2 = new PriorityBlockingQueue<>(5); // Constructor with initial capacity and comparator Comparator<Integer> comparator = Integer::compareTo; BlockingQueue<Integer> queue3 = new PriorityBlockingQueue<>(5, comparator); // Constructor with initial collection of elements Collection<Integer> initialElements = java.util.Arrays.asList(1, 3, 2); BlockingQueue<Integer> queue4 = new PriorityBlockingQueue<>(initialElements)
DelayQueue: En forsinket kø hvor elementer kun kan hentes etter at deres forsinkelse har utløpt.
DelayedElement.java
DelayQueueConstructors.java
123456789101112131415161718class DelayedElement implements Delayed { private final long expirationTime; // The time when the element will be available public DelayedElement(long delay, TimeUnit unit) { this.expirationTime = System.currentTimeMillis() + unit.toMillis(delay); } @Override public long getDelay(TimeUnit unit) { long delay = expirationTime - System.currentTimeMillis(); // Calculate the remaining delay return unit.convert(delay, TimeUnit.MILLISECONDS); // Convert the delay to the specified time unit } @Override public int compareTo(Delayed o) { return Long.compare(this.expirationTime, ((DelayedElement) o).expirationTime); } }
Denne koden demonstrerer bruken av DelayedElement-klassen, som implementerer Delayed-interface, og forsinket kø (DelayQueue) i Java. DelayedElement-klassen definerer en getDelay-metode for å beregne gjenværende forsinkelsestid og en compareTo-metode for å sammenligne objekter basert på utløpstid for forsinkelse.
main-metoden oppretter to køer: queue1, en tom forsinket kø, og queue2, en kø initialisert med elementer som har en forsinkelse på 5 og 1 sekund, henholdsvis.
Elementene i DelayQueueue blir tilgjengelige for henting etter at den angitte forsinkelsestiden har utløpt.
SynchronousQueueue: En kø uten kapasitet, der hver innsettingsoperasjon må vente på den tilsvarende uttaksoperasjonen og omvendt.
Main.java
12345// Constructor without fair access BlockingQueue<String> queue1 = new SynchronousQueue<>(); // Constructor with fair access BlockingQueue<String> queue2 = new SynchronousQueue<>(true);
Hovedmetodene til BlockingQueue:
Legge til elementer:
Metoden void put(E e) setter inn et element i køen, og blokkerer tråden hvis køen er full. Alternativt forsøker metoden boolean offer(E e, long timeout, TimeUnit unit) å legge til et element i køen, og venter i angitt tid hvis køen er full.
Main.java
1234567891011121314151617public class BlockingQueueExample { public static void main(String[] args) { BlockingQueue<String> queue = new ArrayBlockingQueue<>(2); try { queue.put("Element 1"); // Insert the first element, no blocking. queue.put("Element 2"); // Insert the second element, no blocking. // Try to add the third element with a 2-second timeout. // Since the queue is full, it will wait for 2 seconds. boolean success = queue.offer("Element 3", 2, TimeUnit.SECONDS); } catch (InterruptedException e) { e.printStackTrace(); } } }
Dette eksemplet viser innsetting av to elementer i en BlockingQueue uten blokkering, etterfulgt av et forsøk på å legge til et tredje element med en 2-sekunders tidsavbrudd ved bruk av offer()-metoden, som vil vente dersom køen er full.
Henting av element:
Metoden E take() henter og returnerer et element fra køen, og blokkerer tråden dersom køen er tom. Alternativt forsøker metoden E poll(long timeout, TimeUnit unit) å hente et element fra køen, og venter i angitt tid dersom køen er tom.
Main.java
1234567891011121314151617181920212223public class BlockingQueueRetrievalExample { public static void main(String[] args) { BlockingQueue<String> queue = new ArrayBlockingQueue<>(2); try { // Adding elements to the queue queue.put("Element 1"); queue.put("Element 2"); // Retrieve and remove the first element, no blocking since the queue is not empty String item1 = queue.take(); // Returns "Element 1" // Attempt to retrieve and remove the next element with a 2-second timeout String item2 = queue.poll(2, TimeUnit.SECONDS); // Returns "Element 2" // Attempt to retrieve an element when the queue is empty, this will block for 2 seconds String item3 = queue.poll(2, TimeUnit.SECONDS); // Returns `null` after timeout } catch (InterruptedException e) { e.printStackTrace(); } } }
Denne koden legger til to elementer i en BlockingQueue, henter ut og fjerner det første elementet umiddelbart, forsøker å hente ut neste element med en 2-sekunders tidsavbrudd, og prøver til slutt å hente ut et element fra en tom kø, noe som resulterer i null etter tidsavbruddet.
Kontrollere og fjerne elementer:
Metoden boolean remove(Object o) fjerner det spesifiserte elementet fra køen dersom det er til stede. På den annen side kontrollerer metoden boolean contains(Object o) om det spesifiserte elementet finnes i køen uten å fjerne det.
Main.java
1234567891011121314151617181920212223242526public class BlockingQueueCheckRemoveExample { public static void main(String[] args) { BlockingQueue<String> queue = new ArrayBlockingQueue<>(2); try { // Adding elements to the queue queue.put("Element 1"); queue.put("Element 2"); // Check if "Element 1" is in the queue, should return `true` boolean containsElement1 = queue.contains("Element 1"); // true // Remove "Element 1" from the queue, should return `true` boolean removedElement1 = queue.remove("Element 1"); // true // Check if "Element 1" is still in the queue, should return `false` boolean containsElement1AfterRemoval = queue.contains("Element 1"); // false // Try to remove an element that is not in the queue, should return `false` boolean removedElement3 = queue.remove("Element 3"); // false } catch (InterruptedException e) { e.printStackTrace(); } } }
Denne koden legger til to elementer i en BlockingQueue, sjekker om "Element 1" er til stede, fjerner det, sjekker igjen for å bekrefte at det er fjernet, og forsøker deretter å fjerne et ikke-eksisterende element.
Spørring om køens tilstand:
Metoden int size() returnerer antall elementer som for øyeblikket er i køen. For å avgjøre om køen er tom, kan du bruke metoden boolean isEmpty(), som sjekker om køen ikke inneholder noen elementer. For køer med fast kapasitet gir metoden int remainingCapacity() antall gjenværende ledige plasser i køen.
Main.java
123456789101112131415161718192021222324252627282930public class BlockingQueueCapacityExample { public static void main(String[] args) { BlockingQueue<String> queue = new ArrayBlockingQueue<>(3); try { // Adding elements to the queue queue.put("Element 1"); queue.put("Element 2"); // Get the number of elements in the queue int currentSize = queue.size(); // 2 // Check if the queue is empty boolean isQueueEmpty = queue.isEmpty(); // false // Get the remaining capacity in the queue int remainingSpace = queue.remainingCapacity(); // 1 // Add another element to fill the queue queue.put("Element 3"); // Check the size and remaining capacity after adding the third element currentSize = queue.size(); // 3 remainingSpace = queue.remainingCapacity(); // 0 } catch (InterruptedException e) { e.printStackTrace(); } } }
Denne koden legger til elementer i en BlockingQueue, sjekker nåværende størrelse, verifiserer om køen er tom, og fastslår gjenværende kapasitet, deretter oppdateres disse verdiene etter at køen er fylt helt opp.
Realisere et virkelighetsnært eksempel i kode
😭 Begrensninger
En sentral begrensning er ytelse: på grunn av låseoperasjoner kan ytelsen reduseres sammenlignet med ikke-synkroniserte samlinger. I tillegg kan ressurser bli et problem ettersom store køer krever mer minne og prosessor-tid for å håndtere låser og synkroniseringsprosesser.
💪 Fordeler
På den positive siden er systemet trygt i flertrådsmiljø, og gir sikker kommunikasjon mellom tråder uten behov for manuell synkroniseringshåndtering. Det forenkler også koden ved å unngå komplekse synkroniserings- og blokkeringskonstruksjoner. Videre gir fleksibiliteten til ulike BlockingQueue-implementasjoner mulighet for tilpasning til ulike bruksscenarier.
1. Hva er en BlockingQueue i Java?
2. Hva er hovedmetodene i BlockingQueue som blokkerer en tråd?
3. Hva er BlockingQueue nyttig for i flertrådede applikasjoner?
Takk for tilbakemeldingene dine!