- Java 双重比较
- java - 比较器与 Apache BeanComparator
- Objective-C 完成 block 导致额外的方法调用?
- database - RESTful URI 是否应该公开数据库主键?
我有一个简单的程序来生成 CRC32 的输入,它输出一个以 123456(十六进制)结尾的数字。它在工作线程中进行暴力破解(下一步将是创建多个工作线程)。工作线程将结果发送到队列q
。
import java.util.*;
import java.util.concurrent.*;
import java.util.zip.*;
class A {
static final BlockingQueue<List<Byte>> q =
new LinkedBlockingQueue<List<Byte>>();
static {
new Thread() {
public void run() {
System.out.println("worker thread starting");
int len = 1;
byte[] a = new byte[32];
for (int i =0; i < 32; i++) a[i]=-128;
while (true) {
CRC32 crc = new CRC32();
crc.update(a, 0, len);
long x = crc.getValue();
if ((x & 0xffffff) == 0x123456) {
System.out.println("HA " + Arrays.toString(a) + "; " + x);
List<Byte> l = new LinkedList<Byte>();
for (int i = 0; i < a.length; i++) l.add(a[i]);
System.out.println("A");
q.add(l);
System.out.println("B"); // never reaches here
}
// generate next guess
boolean c = true;
for (int i = 0; i < len && c; i++) {
c = ++a[i] == -128;
if (c) if (i + 2 > len) len = i + 2;
}
}
}
}.start();
}
// for stats: amount of inputs found per interval
static long amount = 3;
static long interval;
static {
// record an initial value for interval, so any code using
// it doesn't have to have a special case to check whether
// it's initialized
long start = System.currentTimeMillis();
while (q.size() != amount);
interval = System.currentTimeMillis() - start;
}
public static void main(String[] args) {
System.out.println("main");
}
}
由于某种原因,它卡住了:
$ javac A.java && java A
worker thread starting
HA [-49, 72, 73, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128, -128]; 1376924758
A
工作线程在发送到队列时明显被阻塞 (q.add(l)
),否则,“B”将被打印到控制台。如果我注释掉从队列中读取的行 (while (q.size() != amount)
),它就不会再卡住。我认为这种行为对于无界队列是不可能的(假设其中还没有 2147483647 个元素)。这不是 SynchronousQueue
,因此无论是否有任何线程正在从中接收数据,发送到队列都应该有效。事实上,这种行为似乎与 SynchronousQueue
相反:只有在没有接收者的情况下才发送。
为什么工作线程在尝试发送到队列时被阻塞?
最佳答案
它在 synchronized(A.class)
而不是队列上被阻塞。
当主线程启动时,它会加载类 A。为此,它会同步类本身以有效地加载类。当您启动一个新线程并尝试访问队列时,它将尝试加载该类(因为该类尚未完成加载,因为第二个静态 block 中的自旋很忙)。现在第一个线程拥有类的同步锁,第二个线程将坐在类监视器上,直到第一个线程存在第二个静态(忙自旋)。
运行程序并kill 3
以查看线程转储。您会注意到类长在类里面而不是队列中。
我将尝试说明这一点。
Thread-1
Load Class A
synchronized(A.class){
static: create new Thread (call it Thread-2)
static: busy spin while (q.size() != amount);
}
Thread-2 (after first static)
run(){
A.q
Load Class A
synchronized(A.class){ //block until Thread-1 releases the lock
A.q.add(..);
}
}
关于java - 除非没有接收者,否则无法发送到无限制的 LinkedBlockingQueue?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17408097/
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 9 年前。 Improve
我使用 LinkedBlockingQueue 为我的应用程序进行隐式同步,但如果我使用 queue.take() 或 queue.poll() ,前几个元素总是以某种方式从队列中获取后丢失。我已经检
我正在使用 LinkedBlockingQueue 在线程之间共享一些对象。问题是这个队列中可能有一些重复项。我尝试过这个解决方案: SortedSet set = new TreeSet(new M
如果我运行以下程序,JVM 在执行后不会终止。但是,如果我取消代码中 (//newFixedThreadPool.execute(new Producer3());) 行的注释,程序将在执行后终止。我
我有一个 LinkedBlockingQueue,我想检查队列中的元素是否按一定顺序排列,而不删除元素。我希望有一种方法可以用来查看队列中的特定位置。例如,queue.peekSpot(0) 将返回头
我正在制作一个WordCounter,它有几个线程计算不同文件中的单词。除了一个小问题,我已经把一切都搞定了。 我无法找出等待线程完成的正确方法。如果我设置 Thread.sleep 等待一小段时间,
我想知道为什么不 LinkedBlockingQueue如果我们将底层数据结构更改为像 java.util.LinkedList 这样的非线程安全列表,是否可以工作?当我尝试时,我得到一个 NoSuc
我创建了一个类来计算同一目录中给定文件中的单词数。由于文件非常大,我决定使用多线程来实现多个文件的计数。 当按照下面指定的方式运行 DriverClass 时,它会卡在线程一。我究竟做错了什么?当我迭
我有一个非常基本的线程池代码。它调用位于 linkedblockingqueue 中的工作对象池。该代码只是通过回收工作对象来打印出输入数据。 我发现与以下内容一致的死锁/卡住: public cla
我的情况是单个生产者和单个消费者处理对象队列。队列可能为空有两种情况: 消费者处理对象的速度比生产者生成新对象的速度快(生产者在生成对象之前使用 I/O)。 生产者已完成对象的生成。 如果队列为空,我
我有 3 个线程:2 个消费者,ConsumerA 和 ConsumerB,以及一个 Producer。 我还有一个LinkedBlockingQueue队列 在 t=1 时:ConsumerA 调用
我有一个类似生产者-消费者的场景。 A 类生成 E 类型的对象。我必须将它保存在 A 类的静态数据结构中,因为消费者逻辑应该在 B 类中处理,它没有引用 A 的对象。LinkedBlockingQue
我看着 JDK LinkedBlockingQueue 类,迷路了。 public void put(E e) throws InterruptedException { if (e == n
我的问题涉及使用同步来订购我用于电梯程序的 LinkedBlockingQueue。 在该程序中,电梯应该尽可能高效地运行:从一楼到十楼的电梯将在上升过程中响应额外的停靠,即使这些停靠是在最初的 10
我需要一个 LinkedBlockingQueue 但我正在将原语传递给它。我添加到队列的数据速率约为每秒 4 毫秒或 256 个数据点。我遇到的问题是数据在开始时立即开始延迟,但随着时间的推移,JI
我在两个不同的线程之间使用 LinkedBlockingQueue。一个线程通过add添加数据,而另一个线程通过take接收数据。 我的问题是,我是否需要同步访问 add 和 take。 Linked
ArrayBlockingQueue public class ArrayBlockingQueue extends AbstractQueue implements BlockingQueu
如果尝试向阻塞队列添加超过阻塞队列剩余大小的集合,会发生什么?从我目前阅读的文档中并不清楚这一点。 LinkedBlockingQueue foo = new LinkedBlockingQ
在下面的伪代码中,我有一个 poll() 函数,该函数在主线程中永远被调用。当我在 poll() 中没有使用 sleep() 语句时,每分钟只有 2-3 个项目被另一个线程添加到队列中。这是否意味着轮
当我第一次关注LinkedBlockingQueue中的unlink方法时,我认为trail的第二个参数意味着它是第一个参数-p的下一个节点,但是我错了,因为我在remove方法中发现(Object
我是一名优秀的程序员,十分优秀!