BlockingQueue常用實作類
Java中的BlockingQueue是一個接口,它定義了一組阻塞隊列的操作方法。它的實作類包括:
1. ArrayBlockingQueue:基于數組實作的有界阻塞隊列,必須指定隊列大小。
2. LinkedBlockingQueue:基于連結清單實作的可選有界阻塞隊列,如果不指定隊列大小,則預設大小為Integer.MAX_VALUE。
3. PriorityBlockingQueue:基于堆實作的無界阻塞隊列,元素按照優先級排序。
4. SynchronousQueue:一個不存儲元素的阻塞隊列,每個插入操作必須等待另一個線程的移除操作,反之亦然。
5. DelayQueue:基于PriorityQueue實作,用于存儲實作了Delayed接口的元素,隻有在延遲期滿時才能取出元素。
這些實作類都提供了阻塞隊列的常用方法,如put()、take()、offer()、poll()等,可以友善地實作生産者-消費者模式、任務排程等場景。
常用隊列的使用
BlockingQueue是一個非常有用的資料結構,可以在多線程程式設計中實作線程間的協作和同步。下面是幾個常用的BlockingQueue的使用方法:
- ArrayBlockingQueue:
BlockingQueue<String> queue = new ArrayBlockingQueue<>(10);
queue.put("Hello");
String s = queue.take();
System.out.println(s);
- LinkedBlockingQueue:
BlockingQueue<String> queue = new LinkedBlockingQueue<>();
queue.offer("Hello");
String s = queue.poll();
System.out.println(s);
- PriorityBlockingQueue:
BlockingQueue<Integer> queue = new PriorityBlockingQueue<>();
queue.offer(2);
queue.offer(1);
queue.offer(3);
Integer n = queue.take();
System.out.println(n);
- 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);
- 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的特點:
- 内部使用堆來實作,保證元素的順序性和高效性。
- 是一個無界隊列,即隊列大小可以動态增長,隻受系統資源限制。
- 支援多線程環境下的并發通路,提供了阻塞和非阻塞兩種操作方式。
- 不允許插入null元素。
PriorityBlockingQueue的常用方法:
- add(E e) / offer(E e):添加元素e到隊列中。
- take():移除并傳回隊列頭部的元素,如果隊列為空,則阻塞等待。
- poll():移除并傳回隊列頭部的元素,如果隊列為空,則傳回null。
- peek():傳回隊列頭部的元素,但不移除。
- clear():清空隊列中的元素。
- 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的特點:
- 内部使用PriorityQueue來實作,保證元素的順序性和高效性。
- 隻有在延遲時間到達時才能從隊列中取出元素。
- 是一個無界隊列,即隊列大小可以動态增長,隻受系統資源限制。
- 支援多線程環境下的并發通路,提供了阻塞和非阻塞兩種操作方式。
- 不允許插入null元素。
DelayQueue的常用方法:
- put(E e):添加元素e到隊列中。
- take():移除并傳回隊列頭部的元素,如果隊列為空,則阻塞等待。
- poll():移除并傳回隊列頭部的元素,如果隊列為空,則傳回null。
- peek():傳回隊列頭部的元素,但是不會從隊列中移除。
- 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接口中定義了很多方法,下面是一些常用的方法以及它們的不同點:
- put(E e)和add(E e)
這兩個方法都是用于向隊列中添加元素的方法。不同之處在于,當隊列已滿時,put方法會一直阻塞直到隊列有空閑位置,而add方法則會抛出IllegalStateException異常。
- take()和remove()
這兩個方法都是用于從隊列中取出元素的方法。不同之處在于,當隊列為空時,take方法會一直阻塞直到隊列中有元素可取,而remove方法則會抛出NoSuchElementException異常。
- offer(E e)和offer(E e, long timeout, TimeUnit unit)
這兩個方法都是用于向隊列中添加元素的方法。不同之處在于,當隊列已滿時,offer方法會立即傳回false,而offer方法還可以設定逾時時間,如果在指定時間内隊列仍然沒有空閑位置,則傳回false。
- poll()和poll(long timeout, TimeUnit unit)
這兩個方法都是用于從隊列中取出元素的方法。不同之處在于,當隊列為空時,poll方法會立即傳回null,而poll方法還可以設定逾時時間,如果在指定時間内隊列仍然沒有元素可取,則傳回null。
- remainingCapacity()
這個方法用于傳回隊列中剩餘的可用空間,不同的實作類可能會有不同的實作方式。
總之,BlockingQueue是一個非常有用的接口,它提供了一組阻塞隊列的操作方法,可以幫助我們實作多線程并發場景下的資料交換和協調。在實際應用中,我們可以根據實際需求選擇合适的實作類,并使用其中的方法來完成對隊列的操作。