栈
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
|
package com.yuzhenc.collection; import java.util.Stack; /** * @author: yuzhenc * @date: 2022-03-20 15:41:36 * @desc: com.yuzhenc.collection * @version: 1.0 */ public class Test26 { public static void main(String[] args) { Stack<String> stack = new Stack<>(); stack.add( "A" ); stack.add( "B" ); stack.add( "C" ); stack.add( "D" ); System.out.println(stack); //[A, B, C, D] //判断栈是否为空 System.out.println(stack.empty()); //false //查看栈顶元素,不会移除 System.out.println(stack.peek()); //D System.out.println(stack); //[A, B, C, D] //查看栈顶元素,并且移除,即出栈(先进后出) System.out.println(stack.pop()); //D System.out.println(stack); //[A, B, C] //入栈,和add方法执行的功能一样,就是返回值不同 System.out.println(stack.push( "E" )); //返回入栈的元素 E System.out.println(stack); //[A, B, C, E] } } |
队列
阻塞队列
-
ArrayBlockingQueue
: 不支持读写同时操作,底层基于数组的; -
LinkedBlockingQueue
:支持读写同时操作,并发情况下,效率高,底层基于链表;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
|
package com.yuzhenc.collection; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.TimeUnit; /** * @author: yuzhenc * @date: 2022-03-20 16:00:22 * @desc: com.yuzhenc.collection * @version: 1.0 */ public class Test27 { public static void main(String[] args) throws InterruptedException { ArrayBlockingQueue<String> arrayBlockingQueue = new ArrayBlockingQueue<>( 3 ); //添加元素 //不可以添加null,报空指针异常 //arrayBlockingQueue.add(null); //arrayBlockingQueue.offer(null); //arrayBlockingQueue.put(null); //正常添加元素 System.out.println(arrayBlockingQueue.add( "Lili" )); //true System.out.println(arrayBlockingQueue.offer( "Amy" )); //true arrayBlockingQueue.put( "Nana" ); //无返回值 //队列满的情况下添加元素 //arrayBlockingQueue.add("Sam");//报非法的状态异常 //设置最大注阻塞时间,如果时间到了队列还是满的,就不再阻塞了 arrayBlockingQueue.offer( "Daming" , 3 ,TimeUnit.SECONDS); System.out.println(arrayBlockingQueue); //[Lili, Amy, Nana] //真正阻塞的方法,如果队列一直是满的,就一直阻塞 //arrayBlockingQueue.put("Lingling");//运行到这永远走不下去了,阻塞了 //获取元素 //获取队首元素不移除 System.out.println(arrayBlockingQueue.peek()); //Lili //出队,获取队首元素并且移除 System.out.println(arrayBlockingQueue.poll()); //Lili System.out.println(arrayBlockingQueue); //[Amy, Nana] //获取队首元素,并且移除 System.out.println(arrayBlockingQueue.take()); //Amy System.out.println(arrayBlockingQueue); //[Nana] //清空元素 arrayBlockingQueue.clear(); System.out.println(arrayBlockingQueue); //[] System.out.println(arrayBlockingQueue.peek()); System.out.println(arrayBlockingQueue.poll()); //设置阻塞事件,如果队列为空,返回null,时间到了以后就不阻塞了 System.out.println(arrayBlockingQueue.poll( 2 ,TimeUnit.SECONDS)); //真正的阻塞,队列为空 //System.out.println(arrayBlockingQueue.take());//执行到这里走不下去了 } } |
SynchronousQueue
:方便高效地进行线程间数据的传送,不会产生队列中数据争抢问题;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
|
package com.yuzhenc.collection; import java.util.concurrent.SynchronousQueue; /** * @author: yuzhenc * @date: 2022-03-20 21:06:47 * @desc: com.yuzhenc.collection * @version: 1.0 */ public class Test28 { public static void main(String[] args) { SynchronousQueue sq = new SynchronousQueue(); //创建一个线程,取数据: new Thread( new Runnable() { @Override public void run() { while ( true ){ try { System.out.println(sq.take()); } catch (InterruptedException e) { e.printStackTrace(); } } } }).start(); //搞一个线程,往里面放数据: new Thread( new Runnable() { @Override public void run() { try { sq.put( "aaa" ); sq.put( "bbb" ); sq.put( "ccc" ); sq.put( "ddd" ); } catch (InterruptedException e) { e.printStackTrace(); } } }).start(); } } |
-
PriorityBlockingQueue
:带优先级的阻塞队列; - 无界的队列,没有长度限制,但是在你不指定长度的时候,默认初始长度为11,也可以手动指定,当然随着数据不断的加入,底层(底层是数组Object[])会自动扩容,直到内存全部消耗殆尽了,导致 OutOfMemoryError内存溢出 程序才会结束;
-
不可以放入null元素的,不允许放入不可比较的对象(导致抛
ClassCastException
),对象必须实现内部比较器或者外部比较器;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
|
package com.yuzhenc.collection; import java.util.concurrent.PriorityBlockingQueue; /** * @author: yuzhenc * @date: 2022-03-20 21:16:56 * @desc: com.yuzhenc.collection * @version: 1.0 */ public class Test29 { public static void main(String[] args) throws InterruptedException { PriorityBlockingQueue<Human> priorityBlockingQueue = new PriorityBlockingQueue<>(); priorityBlockingQueue.put( new Human( "Lili" , 25 )); priorityBlockingQueue.put( new Human( "Nana" , 18 )); priorityBlockingQueue.put( new Human( "Amy" , 38 )); priorityBlockingQueue.put( new Human( "Sum" , 9 )); //没有按优先级排列 System.out.println(priorityBlockingQueue); //[Human{name='Sum', age=9}, Human{name='Nana', age=18}, Human{name='Amy', age=38}, Human{name='Lili', age=25}] //出列的时候按优先级出列 System.out.println(priorityBlockingQueue.take()); //Human{name='Sum', age=9} System.out.println(priorityBlockingQueue.take()); //Human{name='Nana', age=18} System.out.println(priorityBlockingQueue.take()); //Human{name='Lili', age=25} System.out.println(priorityBlockingQueue.take()); //Human{name='Amy', age=38} } } class Human implements Comparable <Human> { String name; int age; public Human() {} public Human(String name, int age) { this .name = name; this .age = age; } public String getName() { return name; } public void setName(String name) { this .name = name; } public int getAge() { return age; } public void setAge( int age) { this .age = age; } @Override public String toString() { return "Human{" + "name='" + name + '\ '' + ", age=" + age + '}' ; } @Override public int compareTo(Human o) { return this .age-o.age; } |
-
DelayQueue
:DelayQueue是一个无界的BlockingQueue
,用于放置实现了Delayed接口的对象,其中的对象只能在其到期时才能从队列中取走; - 当生产者线程调用put之类的方法加入元素时,会触发Delayed接口中的compareTo方法进行排序,也就是说队列中元素的顺序是按到期时间排序的,而非它们进入队列的顺序。排在队列头部的元素是最早到期的,越往后到期时间越晚;
- 消费者线程查看队列头部的元素,注意是查看不是取出。然后调用元素的getDelay方法,如果此方法返回的值小0或者等于0,则消费者线程会从队列中取出此元素,并进行处理。如果getDelay方法返回的值大于0,则消费者线程wait返回的时间值后,再从队列头部取出元素,此时元素应该已经到期;
- 不能将null元素放置到这种队列中;
-
DelayQueue能做什么
- 淘宝订单业务:下单之后如果三十分钟之内没有付款就自动取消订单;
- 饿了吗订餐通知:下单成功后60s之后给用户发送短信通知;
- 关闭空闲连接。服务器中,有很多客户端的连接,空闲一段时间之后需要关闭之;
- 缓存。缓存中的对象,超过了空闲时间,需要从缓存中移出;
- 任务超时处理。在网络协议滑动窗口请求应答式交互时,处理超时未响应的请求等;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
|
package com.yuzhenc.collection; import java.util.concurrent.DelayQueue; import java.util.concurrent.Delayed; import java.util.concurrent.TimeUnit; /** * @author: yuzhenc * @date: 2022-03-20 21:43:32 * @desc: com.yuzhenc.collection * @version: 1.0 */ public class Test30 { //创建一个队列: DelayQueue<User> dq = new DelayQueue<>(); //登录游戏: public void login(User user){ dq.add(user); System.out.println( "用户:[" + user.getId() + "],[" + user.getName() + "]已经登录,预计下机时间为:" + user.getEndTime() ); } //时间到,退出游戏,队列中移除: public void logout(){ //打印队列中剩余的人: System.out.println(dq); try { User user = dq.take(); System.out.println( "用户:[" + user.getId() + "],[" + user.getName() + "]上机时间到,自动退出游戏" ); } catch (InterruptedException e) { e.printStackTrace(); } } //获取在线人数: public int onlineSize(){ return dq.size(); } //这是main方法,程序的入口 public static void main(String[] args) { //创建测试类对象: Test30 test = new Test30(); //添加登录的用户: test.login( new User( 1 , "张三" ,System.currentTimeMillis()+ 5000 )); test.login( new User( 2 , "李四" ,System.currentTimeMillis()+ 2000 )); test.login( new User( 3 , "王五" ,System.currentTimeMillis()+ 10000 )); //一直监控 while ( true ){ //到期的话,就自动下线: test.logout(); //队列中元素都被移除了的话,那么停止监控,停止程序即可 if (test.onlineSize() == 0 ){ break ; } } } } class User implements Delayed { private int id; //用户id private String name; //用户名字 private long endTime; //结束时间 public int getId() { return id; } public void setId( int id) { this .id = id; } public String getName() { return name; } public void setName(String name) { this .name = name; } public long getEndTime() { return endTime; } public void setEndTime( long endTime) { this .endTime = endTime; } public User( int id, String name, long endTime) { this .id = id; this .name = name; this .endTime = endTime; } //只包装用户名字就可以 @Override public String toString() { return "User{" + "name='" + name + '\ '' + '}' ; } @Override public long getDelay(TimeUnit unit) { //计算剩余时间 剩余时间小于0 <=0 证明已经到期 return this .getEndTime() - System.currentTimeMillis(); } @Override public int compareTo(Delayed o) { //队列中数据 到期时间的比较 User other = (User)o; return ((Long)( this .getEndTime())).compareTo((Long)(other.getEndTime())); } } |
双端队列
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
package com.yuzhenc.collection; import java.util.Deque; import java.util.LinkedList; /** * @author: yuzhenc * @date: 2022-03-20 22:03:36 * @desc: com.yuzhenc.collection * @version: 1.0 */ public class Test31 { public static void main(String[] args) { /* 双端队列: Deque<E> extends Queue Queue一端放 一端取的基本方法 Deque是具备的 在此基础上 又扩展了 一些 头尾操作(添加,删除,获取)的方法 */ Deque<String> d = new LinkedList<>() ; d.offer( "A" ); d.offer( "B" ); d.offer( "C" ); System.out.println(d); //[A, B, C] d.offerFirst( "D" ); d.offerLast( "E" ); System.out.println(d); //[D, A, B, C, E] System.out.println(d.poll()); //D System.out.println(d); //[A, B, C, E] System.out.println(d.pollFirst()); //A System.out.println(d.pollLast()); //E System.out.println(d); //[B, C] } } |
总结
本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注服务器之家的更多内容!
原文链接:https://blog.csdn.net/qq_33445829/article/details/123614633