admin管理员组文章数量:1300024
Unexpected behavior with 2 enqueuer threads when using built-in java ArrayBlockingQueue
and custom implementation
The behavior is that I expected is that each threads enqueues and deques in the sequential order that the threads used in enqueue the values, but this is not the case.
This is the code:
public class MultiThreadTests {
private static final int QUEUE_LENGTH = 100_000;
public static void main(String[] args) throws InterruptedException {
usingTwoThreadsAndArrayBlockingQueue();
}
private static void usingTwoThreadsAndArrayBlockingQueue() throws InterruptedException {
ArrayBlockingQueue<Integer> q = new ArrayBlockingQueue<Integer>(QUEUE_LENGTH);
ArrayBlockingQueueClientThread t1 = new ArrayBlockingQueueClientThread(q, 1);
ArrayBlockingQueueClientThread t2 = new ArrayBlockingQueueClientThread(q, 2000);
t1.start();
t2.start();
}
static class ArrayBlockingQueueClientThread extends Thread {
ArrayBlockingQueue q;
int m;
ArrayBlockingQueueClientThread(ArrayBlockingQueue ephemeralQueue, int m) {
this.q = ephemeralQueue;
this.m = m;
}
public void run() {
for (int i = 0; i < 20 ; i++) {
q.add(i * m);
}
// I should still see the correct order when I dequeue concurrently, but I do not.
int k = 0;
while(k<20)
{
k++;
try {
System.out.println(q.poll(500, TimeUnit.MILLISECONDS));
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
This is the output (it is not consistent however): | | | ----- | | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | | 7 | | 8 | | 9 | | 0 | | 11 | | 12 | | 13 | | 10 | | 14 | | 16 | | 17 | | 18 | | 19 | | 0 | | 2000 | | 4000 | | 15 | | 8000 | | 10000 | | 12000 | | 14000 | | 16000 | | 18000 | | 6000 | | 22000 | | 24000 | | 26000 | | 28000 | | 30000 | | 20000 | | 34000 | | 36000 | | 32000 | | 38000 |
Some values are out of order
at the thread level, such as value 15 and the value 6000. and I do not understand why this is the case. Any help is greatly appreciated.
Unexpected behavior with 2 enqueuer threads when using built-in java ArrayBlockingQueue
and custom implementation
The behavior is that I expected is that each threads enqueues and deques in the sequential order that the threads used in enqueue the values, but this is not the case.
This is the code:
public class MultiThreadTests {
private static final int QUEUE_LENGTH = 100_000;
public static void main(String[] args) throws InterruptedException {
usingTwoThreadsAndArrayBlockingQueue();
}
private static void usingTwoThreadsAndArrayBlockingQueue() throws InterruptedException {
ArrayBlockingQueue<Integer> q = new ArrayBlockingQueue<Integer>(QUEUE_LENGTH);
ArrayBlockingQueueClientThread t1 = new ArrayBlockingQueueClientThread(q, 1);
ArrayBlockingQueueClientThread t2 = new ArrayBlockingQueueClientThread(q, 2000);
t1.start();
t2.start();
}
static class ArrayBlockingQueueClientThread extends Thread {
ArrayBlockingQueue q;
int m;
ArrayBlockingQueueClientThread(ArrayBlockingQueue ephemeralQueue, int m) {
this.q = ephemeralQueue;
this.m = m;
}
public void run() {
for (int i = 0; i < 20 ; i++) {
q.add(i * m);
}
// I should still see the correct order when I dequeue concurrently, but I do not.
int k = 0;
while(k<20)
{
k++;
try {
System.out.println(q.poll(500, TimeUnit.MILLISECONDS));
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
}
}
This is the output (it is not consistent however): | | | ----- | | 1 | | 2 | | 3 | | 4 | | 5 | | 6 | | 7 | | 8 | | 9 | | 0 | | 11 | | 12 | | 13 | | 10 | | 14 | | 16 | | 17 | | 18 | | 19 | | 0 | | 2000 | | 4000 | | 15 | | 8000 | | 10000 | | 12000 | | 14000 | | 16000 | | 18000 | | 6000 | | 22000 | | 24000 | | 26000 | | 28000 | | 30000 | | 20000 | | 34000 | | 36000 | | 32000 | | 38000 |
Some values are out of order
at the thread level, such as value 15 and the value 6000. and I do not understand why this is the case. Any help is greatly appreciated.
2 Answers
Reset to default 4Why do you expect sequential order?
The execution could be:
- the first thread reads "0" from the queue
- the second thread reads "1" and prints it, reads "2" and prints it, ..., reads "9" and prints it, reads "10"
- the first thread manages to print out the "0" it fetched long ago, then reads "11" and prints it, reads "12" and prints it, reads "13" and prints it
- the second thread prints out the "10", reads "14" and prints it
- the first thread reads "15"
In your given code, q.add(...) and q.poll() may alternate.
t1 may have add(0), but t2 may have poll() the 0, causing t1 to poll() again, possibly taking the number that t2 inserted.
Because the poll() operation is competitive, there is no control over who poll() first to take out the head of the queue.
For Example:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19]
0
1
2
3
[3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 0, 2000, 4000, 6000, 8000, 10000, 12000, 14000, 16000, 18000, 20000, 22000, 24000, 26000, 28000, 30000, 32000, 34000, 36000, 38000]
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
0
2000
4000
6000
8000
4
10000
12000
14000
16000
18000
20000
22000
24000
26000
28000
30000
32000
34000
36000
38000
本文标签:
版权声明:本文标题:multithreading - Unexpected behavior with 2 enqueuing threads when using built-in java ArrayBlockingQueue and custom implementat 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1741654393a2390670.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论