天天看點

BlockingQueue知識合集

作者:四季更新221789896

BlockingQueue常用實作類

Java中的BlockingQueue是一個接口,它定義了一組阻塞隊列的操作方法。它的實作類包括:

1. ArrayBlockingQueue:基于數組實作的有界阻塞隊列,必須指定隊列大小。

2. LinkedBlockingQueue:基于連結清單實作的可選有界阻塞隊列,如果不指定隊列大小,則預設大小為Integer.MAX_VALUE。

3. PriorityBlockingQueue:基于堆實作的無界阻塞隊列,元素按照優先級排序。

4. SynchronousQueue:一個不存儲元素的阻塞隊列,每個插入操作必須等待另一個線程的移除操作,反之亦然。

5. DelayQueue:基于PriorityQueue實作,用于存儲實作了Delayed接口的元素,隻有在延遲期滿時才能取出元素。

這些實作類都提供了阻塞隊列的常用方法,如put()、take()、offer()、poll()等,可以友善地實作生産者-消費者模式、任務排程等場景。

常用隊列的使用

BlockingQueue是一個非常有用的資料結構,可以在多線程程式設計中實作線程間的協作和同步。下面是幾個常用的BlockingQueue的使用方法:

  1. ArrayBlockingQueue:
BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
queue.put("Hello");
String s = queue.take();
System.out.println(s);           
  1. LinkedBlockingQueue:
BlockingQueue<String> queue = new LinkedBlockingQueue<>();
queue.offer("Hello");
String s = queue.poll();
System.out.println(s);           
  1. PriorityBlockingQueue:
BlockingQueue<Integer> queue = new PriorityBlockingQueue<>();
queue.offer(2);
queue.offer(1);
queue.offer(3);
Integer n = queue.take();
System.out.println(n);           
  1. SynchronousQueue:
BlockingQueue<String> queue = new SynchronousQueue<>();
new Thread(() -> {
    try {
        queue.put("Hello");
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}).start();
String s = queue.take();
System.out.println(s);           
  1. DelayQueue:
BlockingQueue<DelayedElement> queue = new DelayQueue<>();
queue.offer(new DelayedElement("Hello", 1000));
DelayedElement e = queue.take();
System.out.println(e.getData());           

PriorityBlockingQueue詳解

PriorityBlockingQueue是Java集合架構中的一個阻塞隊列實作類,它可以按照優先級對元素進行排序。在PriorityBlockingQueue中,元素必須實作Comparable接口或者在建立PriorityBlockingQueue時提供一個Comparator對象,用于比較元素的優先級。

PriorityBlockingQueue的特點:

  1. 内部使用堆來實作,保證元素的順序性和高效性。
  2. 是一個無界隊列,即隊列大小可以動态增長,隻受系統資源限制。
  3. 支援多線程環境下的并發通路,提供了阻塞和非阻塞兩種操作方式。
  4. 不允許插入null元素。

PriorityBlockingQueue的常用方法:

  1. add(E e) / offer(E e):添加元素e到隊列中。
  2. take():移除并傳回隊列頭部的元素,如果隊列為空,則阻塞等待。
  3. poll():移除并傳回隊列頭部的元素,如果隊列為空,則傳回null。
  4. peek():傳回隊列頭部的元素,但不移除。
  5. clear():清空隊列中的元素。
  6. size():傳回隊列中的元素個數。

PriorityBlockingQueue的使用示例:

PriorityBlockingQueue<Integer> queue = new PriorityBlockingQueue<>();
queue.offer(3);
queue.offer(1);
queue.offer(2);
System.out.println(queue.poll()); // 1
System.out.println(queue.poll()); // 2
System.out.println(queue.poll()); // 3           

在上面的示例中,我們向PriorityBlockingQueue中添加了3個元素,然後依次取出元素,并按照優先級從小到大輸出。優先級的比較是通過元素的自然順序或Comparator對象來實作的。

Comparable接口

Comparable接口是Java中的一個接口,它定義了一個compareTo()方法,用于比較目前對象和另一個對象的大小關系。實作了Comparable接口的類可以進行自然排序,即按照對象的預設順序進行排序,例如數字從小到大、字元串按照字典順序等。

Comparable接口的定義如下:

public interface Comparable<T> {
    public int compareTo(T o);
}           

其中,compareTo方法傳回一個整數值,表示目前對象和參數對象之間的大小關系。如果目前對象小于參數對象,則傳回負數;如果目前對象等于參數對象,則傳回0;如果目前對象大于參數對象,則傳回正數。

實作了Comparable接口的類可以直接調用Collections.sort()方法或Arrays.sort()方法進行排序。例如,如果我們有一個Person類,其中有一個age屬性,實作了Comparable接口如下:

public class Person implements Comparable<Person> {
    private int age;

    public Person(int age) {
        this.age = age;
    }

    public int getAge() {
        return age;
    }

    @Override
    public int compareTo(Person o) {
        return this.age - o.age;
    }
}           

在上面的代碼中,我們實作了compareTo方法,按照age屬性的大小進行比較。然後可以用以下代碼進行排序:

List<Person> persons = new ArrayList<>();
persons.add(new Person(20));
persons.add(new Person(18));
persons.add(new Person(25));
Collections.sort(persons);           

在這個例子中,我們将三個Person對象添加到一個ArrayList中,然後調用Collections.sort()方法進行排序。由于Person類實作了Comparable接口,是以可以直接調用sort()方法進行自然排序。

總之,Comparable接口是Java集合架構中非常重要的一個接口,它可以幫助我們實作對象的自然排序。

Comparator接口的使用

Comparator是Java集合架構中的一個接口,用于定義對象之間的比較規則,可以通過實作Comparator接口來實作自定義的比較規則。與Comparable接口不同的是,Comparator接口可以用于對任意類型的對象進行比較,而不需要修改對象類的定義。

Comparator接口的定義如下:

public interface Comparator<T> {
    int compare(T o1, T o2);
    boolean equals(Object obj);
}           

其中,compare方法用于比較兩個對象的大小關系,如果o1小于o2,則傳回負數;如果o1等于o2,則傳回0;如果o1大于o2,則傳回正數。equals方法用于比較兩個對象是否相等,通常不需要實作。

Comparator接口的實作類通常可以作為參數傳遞給Java集合架構中的排序方法,例如Collections.sort()方法或Arrays.sort()方法。下面是一個使用Comparator接口實作自定義比較規則的例子:

public class Person {
    private int age;
    private String name;

    public Person(int age, String name) {
        this.age = age;
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public String getName() {
        return name;
    }
}

public class PersonComparator implements Comparator<Person> {
    @Override
    public int compare(Person o1, Person o2) {
        int result = o1.getAge() - o2.getAge();
        if (result == 0) {
            result = o1.getName().compareTo(o2.getName());
        }
        return result;
    }
}

// 使用PersonComparator對Person對象進行排序
List<Person> persons = new ArrayList<>();
persons.add(new Person(20, "Alice"));
persons.add(new Person(18, "Bob"));
persons.add(new Person(25, "Charlie"));
Collections.sort(persons, new PersonComparator());           

在這個例子中,我們實作了一個PersonComparator類,實作了Comparator接口中的compare方法。在compare方法中,我們首先按照age屬性的大小進行比較,如果age相等,則按照name屬性進行比較。然後可以用以下代碼進行排序:

Collections.sort(persons, new PersonComparator());           

在這個例子中,我們将三個Person對象添加到一個ArrayList中,然後調用Collections.sort()方法進行排序。由于我們傳入了一個PersonComparator執行個體,是以排序會按照我們自定義的規則進行。

總之,Comparator接口是Java集合架構中非常重要的一個接口,它可以幫助我們實作自定義的比較規則,适用于一些需要特定排序順序的場景。

DelayQueue詳解

DelayQueue是Java集合架構中的一個阻塞隊列實作類,它可以按照延遲時間對元素進行排序。在DelayQueue中,元素必須實作Delayed接口,Delayed接口定義了getDelay()方法,用于傳回元素的延遲時間。

DelayQueue的特點:

  1. 内部使用PriorityQueue來實作,保證元素的順序性和高效性。
  2. 隻有在延遲時間到達時才能從隊列中取出元素。
  3. 是一個無界隊列,即隊列大小可以動态增長,隻受系統資源限制。
  4. 支援多線程環境下的并發通路,提供了阻塞和非阻塞兩種操作方式。
  5. 不允許插入null元素。

DelayQueue的常用方法:

  1. put(E e):添加元素e到隊列中。
  2. take():移除并傳回隊列頭部的元素,如果隊列為空,則阻塞等待。
  3. poll():移除并傳回隊列頭部的元素,如果隊列為空,則傳回null。
  4. peek():傳回隊列頭部的元素,但是不會從隊列中移除。
  5. size():傳回隊列中元素的數量。

下面是一個使用DelayQueue實作延遲任務的例子:

public class DelayedTask implements Delayed {
    private String name;
    private long endTime;

    public DelayedTask(String name, long delay) {
        this.name = name;
        this.endTime = System.currentTimeMillis() + delay;
    }

    @Override
    public long getDelay(TimeUnit unit) {
        long diff = endTime - System.currentTimeMillis();
        return unit.convert(diff, TimeUnit.MILLISECONDS);
    }

    @Override
    public int compareTo(Delayed o) {
        long diff = this.getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS);
        return (int) diff;
    }

    public String getName() {
        return name;
    }
}

public class DelayedTaskDemo {
    public static void main(String[] args) throws InterruptedException {
        DelayQueue<DelayedTask> queue = new DelayQueue<>();
        queue.put(new DelayedTask("task1", 5000));
        queue.put(new DelayedTask("task2", 3000));
        queue.put(new DelayedTask("task3", 8000));
        while (!queue.isEmpty()) {
            DelayedTask task = queue.take();
            System.out.println(task.getName() + " is executed at " + new Date());
        }
    }
}           

在這個例子中,我們定義了一個DelayedTask類,實作了Delayed接口。在DelayedTask類中,我們定義了一個endTime屬性,表示任務的結束時間,然後實作了getDelay()方法和compareTo()方法。

在main方法中,我們建立了一個DelayQueue對象,并向其中添加了三個DelayedTask對象,分别表示三個延遲任務。然後我們使用while循環從隊列中取出元素,并執行對應的任務。

在運作這個程式時,我們會發現任務按照延遲時間的順序執行,即先執行task2,然後執行task1,最後執行task3。

總之,DelayQueue是一個非常有用的阻塞隊列實作類,它可以幫助我們實作延遲任務的排程等場景。在實際應用中,我們可以根據實際需求來定義Delayed接口的實作類,并使用DelayQueue來管理這些延遲任務。

阻塞隊裡中擷取元素與添加元素方法有哪些不同

BlockingQueue接口中定義了很多方法,下面是一些常用的方法以及它們的不同點:

  1. put(E e)和add(E e)

這兩個方法都是用于向隊列中添加元素的方法。不同之處在于,當隊列已滿時,put方法會一直阻塞直到隊列有空閑位置,而add方法則會抛出IllegalStateException異常。

  1. take()和remove()

這兩個方法都是用于從隊列中取出元素的方法。不同之處在于,當隊列為空時,take方法會一直阻塞直到隊列中有元素可取,而remove方法則會抛出NoSuchElementException異常。

  1. offer(E e)和offer(E e, long timeout, TimeUnit unit)

這兩個方法都是用于向隊列中添加元素的方法。不同之處在于,當隊列已滿時,offer方法會立即傳回false,而offer方法還可以設定逾時時間,如果在指定時間内隊列仍然沒有空閑位置,則傳回false。

  1. poll()和poll(long timeout, TimeUnit unit)

這兩個方法都是用于從隊列中取出元素的方法。不同之處在于,當隊列為空時,poll方法會立即傳回null,而poll方法還可以設定逾時時間,如果在指定時間内隊列仍然沒有元素可取,則傳回null。

  1. remainingCapacity()

這個方法用于傳回隊列中剩餘的可用空間,不同的實作類可能會有不同的實作方式。

總之,BlockingQueue是一個非常有用的接口,它提供了一組阻塞隊列的操作方法,可以幫助我們實作多線程并發場景下的資料交換和協調。在實際應用中,我們可以根據實際需求選擇合适的實作類,并使用其中的方法來完成對隊列的操作。

繼續閱讀