并发集合:ConcurentLinkedDeque

并发集合详解
本文深入探讨了Java中的阻塞式和非阻塞式集合的特点及应用,对比了ConcurrentLinkedDeque与LinkedBlockingDeque的区别,并通过实例代码展示了PriorityBlockingQueue和DelayQueue的工作原理。

阻塞式集合:这类集合包括添加和移除数据的方法。当集合已满或者为空时,被调用的添加或者移除方法不能立即被执行,那么调用这个方法的线程被阻塞,一直到该方法可以被成功执行。如LinkedBlockingDeque\PriorityBlockingQueue
非阻塞式集合:这类集合也包括添加和移除数据的方法。如果方法不能立即被执行,则返回null或抛出异常,但调用这个方法的线程不会被阻塞。如ConcurentLinkedDeque\DelayQueue

ConcurrentLinkedDeque/LinkedBlockingDeque

package mytest;

import java.util.concurrent.ConcurrentLinkedDeque;

/**
 * ConcurentLinkedDeque: 线程安全的、非阻塞式的、双端、无界队列<br>
 * 
 * peek()/peekFirst()/peekLast:返回列表中第一个或最后一个,返回的元素不会从列表中移除,如果列表为空,则返回null
 * getFirst/getLast:返回列表中第一个或最后一个,返回的元素不会从列表中移除,如果列表为空,则抛出NoSuchElementException
 * 
 * pollFist/pollLast:移除元素,如果列表为空,则返回null
 * removeFirst/removeLast/remove:移除元素,如果列表为空,则抛出NoSuchElementException
 * 
 */
public class ConcurentLinkedDequeTest {
    private static ConcurrentLinkedDeque<Integer> cld = new ConcurrentLinkedDeque<Integer>();
    //可以指定队列大小,不指定时,为Integer.MAX_VALUE.Blocking意味着会有阻塞机制
    private static LinkedBlockingDeque<Integer> lbd = new LinkedBlockingDeque<Integer>();

    static class AddTask implements Runnable {
        public void run() {
            for (int i = 0; i < 1000; i++) {
                cld.add(i);
            }
        }
    }

    static class PollTask implements Runnable {
        public void run() {
            for (int i = 0; i < 500; i++) {
                cld.pollFirst();
                cld.pollLast();
                cld.pollLast();
            }
        }
    }

    public static void main(String[] args) {
        // 创建添加线程任务
        Thread[] threads = new Thread[10];
        for (int i = 0; i < threads.length; i++) {
            Thread at = new Thread(new AddTask());
            threads[i] = at;
            threads[i].start();
        }
        System.out.println("add task threads have been lauched.count:" + threads.length);
        for (int i = 0; i < threads.length; i++) {
            try {
                threads[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("size of list :" + cld.size());

        for (int i = 0; i < threads.length; i++) {
            Thread at = new Thread(new PollTask());
            threads[i] = at;
            threads[i].start();
        }
        System.out.println("poll task threads have been lauched.count:" + threads.length);
        for (int i = 0; i < threads.length; i++) {
            try {
                threads[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println("size of list :" + cld.size());
    }
}

输出

add task threads have been lauched.count:10
size of list :10000
poll task threads have been lauched.count:10
size of list :0

PriorityBlockingQueue

package mytest;

import java.util.concurrent.PriorityBlockingQueue;

//有序组合队列
//当插入元素时,PriorityBlockingQueue使用compareTo方法来决定插入元素的位置,元素越大越靠后
public class PriorityBlockingQueueTest {
    static class Event implements Comparable<Event> {
        private int thread;
        private int priority;

        public Event(int thread, int priority) {
            this.thread = thread;
            this.priority = priority;
        }

        public int getThread() {
            return thread;
        }

        public int getPriority() {
            return priority;
        }

        @Override
        public int compareTo(Event o) {
            if (this.priority > o.getPriority()) {
                return -1;
            } else if (this.priority < o.getPriority()) {
                return 1;
            }
            return 0;
        }

    }

    static class Task implements Runnable {
        private int id;
        private PriorityBlockingQueue queue;

        public Task(int id, PriorityBlockingQueue<Event> queue) {
            this.id = id;
            this.queue = queue;
        }

        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                Event event = new Event(id, i);
                queue.add(event);
            }
        }
    }

    public static void main(String[] args) {
        PriorityBlockingQueue<Event> queue = new PriorityBlockingQueue<Event>();
        Thread taskThread[] = new Thread[5];
        for (int i = 0; i < taskThread.length; i++) {
            Task task = new Task(i, queue);
            taskThread[i] = new Thread(task);
        }
        for (int i = 0; i < taskThread.length; i++) {
            taskThread[i].start();
        }
        for (int i = 0; i < taskThread.length; i++) {
            try {
                taskThread[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        for (int i = 0; i < taskThread.length * 100; i++) {
            Event poll = queue.poll();
            System.out.println("thread :" + poll.getThread() + ";priority:" + poll.getPriority());
        }
    }
}

输出结果

thread :1;priority:99
thread :4;priority:99
thread :2;priority:99
thread :0;priority:99
thread :3;priority:99
thread :1;priority:98
thread :4;priority:98
thread :2;priority:98
thread :0;priority:98
thread :3;priority:98

DelayQueue

package mytest;

import java.util.Date;
import java.util.concurrent.DelayQueue;
import java.util.concurrent.Delayed;
import java.util.concurrent.PriorityBlockingQueue;
import java.util.concurrent.TimeUnit;

//DelayQueue中的元素必须继承Delayed接口。该接口使对象成为延迟对象,它使放在DelayQueue中的对象具有激活日期
//未到期的元素你是获取不到嘀
public class DelayQueueTest {
    static class Event implements Delayed {
        private Date startDate;

        public Event(Date startDate) {
            this.startDate = startDate;
        }

        @Override
        public int compareTo(Delayed o) {
            // 将毫秒转换成纳秒进行比较
            long result = this.getDelay(TimeUnit.NANOSECONDS) - o.getDelay(TimeUnit.NANOSECONDS);
            if (result < 0) {
                return -1;
            } else if (result > 0) {
                return 1;
            }
            return 0;
        }

        @Override
        public long getDelay(TimeUnit unit) {
            Date now = new Date();
            long diff = startDate.getTime() - now.getTime();
            return unit.convert(diff, TimeUnit.MILLISECONDS);// 激活日期到当前日期的毫秒数;diff和第二个参数类型一致
        }

    }

    static class Task implements Runnable {
        private int id;
        private DelayQueue queue;

        public Task(int id, DelayQueue<Event> queue) {
            this.id = id;
            this.queue = queue;
        }

        @Override
        public void run() {
            Date now = new Date();
            Date delay = new Date();
            delay.setTime(now.getTime() + (id * 5000));
            System.out.println("Thread id:" + id + ";delay:" + delay);
            for (int i = 0; i < 100; i++) {
                Event event = new Event(delay);
                queue.add(event);
            }
        }
    }

    public static void main(String[] args) throws InterruptedException {
        Date now = new Date();
        long minutes = TimeUnit.HOURS.toMinutes(1);
        System.out.println(minutes);
        System.out.println(TimeUnit.NANOSECONDS.convert(1000L, TimeUnit.MILLISECONDS));

        DelayQueue<Event> queue = new DelayQueue<Event>();
        Thread taskThread[] = new Thread[5];
        for (int i = 0; i < taskThread.length; i++) {
            Task task = new Task(i + 1, queue);
            taskThread[i] = new Thread(task);
        }
        for (int i = 0; i < taskThread.length; i++) {
            taskThread[i].start();
        }
        for (int i = 0; i < taskThread.length; i++) {
            try {
                taskThread[i].join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        do {
            int counter = 0;
            Event event;
            do {
                // 只取已经到了激活时间的event
                event = queue.poll();
                if (event != null)
                    counter++;
            } while (event != null);
            System.out.println("At " + new Date() + " you have read " + counter + " events");
            TimeUnit.SECONDS.sleep(1);//休息1秒尝试取一次
        } while (queue.size() > 0);// 一直等到将队列取光
    }

}

结果:可见5秒钟激活一组数据

At Tue Mar 21 15:48:32 CST 2017 you have read 0 events
At Tue Mar 21 15:48:33 CST 2017 you have read 0 events
At Tue Mar 21 15:48:34 CST 2017 you have read 0 events
At Tue Mar 21 15:48:35 CST 2017 you have read 0 events
At Tue Mar 21 15:48:36 CST 2017 you have read 0 events
At Tue Mar 21 15:48:37 CST 2017 you have read 100 events
At Tue Mar 21 15:48:38 CST 2017 you have read 0 events
At Tue Mar 21 15:48:39 CST 2017 you have read 0 events
At Tue Mar 21 15:48:40 CST 2017 you have read 0 events
At Tue Mar 21 15:48:41 CST 2017 you have read 0 events
At Tue Mar 21 15:48:42 CST 2017 you have read 100 events
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值