Java 队列工作线程停止工作,线程安全问题?
我想先介绍一下我的问题 我有几个WorkingReads,它们接收字符串,处理字符串,然后将处理后的字符串发送到全局队列,如下所示:Java 队列工作线程停止工作,线程安全问题?,java,multithreading,thread-safety,Java,Multithreading,Thread Safety,我想先介绍一下我的问题 我有几个WorkingReads,它们接收字符串,处理字符串,然后将处理后的字符串发送到全局队列,如下所示: class Main { public static Queue<String> Q; public static void main(String[] args) { //start working threads } } 因此,现在每800毫秒,另一个名为Inserter的线程就会将所有条目排出队列,以形成一些sql,但这并不
class Main {
public static Queue<String> Q;
public static void main(String[] args) {
//start working threads
}
}
因此,现在每800毫秒,另一个名为Inserter的线程就会将所有条目排出队列,以形成一些sql,但这并不重要
class Inserter extends Thread {
public void run() {
while(!Main.Q.isEmpty()) {
System.out.print(".");
// dequeue and formulate some SQL
}
}
}
每样东西都能工作大约5到10分钟,但突然,我看不到任何打印的点(基本上是插入器的心跳)。队列不是空的,我可以保证,但插入器只是不工作,即使它得到定期启动
我怀疑当插入器退出队列时,工作人员想要插入某些内容时会出现问题,这可能是某种“死锁”吗
我真希望有人能对这种行为做出解释。我期待着学习;)
编辑:我正在使用
Queue<String> Q = new LinkedList<String>();
Queue Q=newlinkedlist();
您需要同步对队列的访问,或者
使用ConcurrentLinkedQueue请参见
或者建议使用BlockingQueue(取决于您的要求)
有关BlockingQueue的更详细说明,请参阅
您需要同步对队列的访问,或者 使用ConcurrentLinkedQueue请参见 或者建议使用BlockingQueue(取决于您的要求) 有关BlockingQueue的更详细说明,请参阅
看起来更像是同步问题。。您正在尝试模拟-
生产者-消费者问题
。您需要同步队列或使用阻塞队列
。您可能有竞争条件。更像是同步问题。。您正在尝试模拟-生产者-消费者问题
。您需要同步队列或使用阻塞队列
。您可能有竞态条件。您没有使用同步的或线程安全的队列
,因此存在竞态风险。您使用LinkedList
表明您对这一事实缺乏了解(有点可怕)。在尝试处理更多的线程化代码之前,您可能需要阅读更多关于线程和线程安全的内容
您必须手动同步或使用JDK提供的现有实现之一。生产者/消费者模式通常使用BlockingQueue
实现之一实现
如果队列已满,则大小有界的阻塞队列
将阻止试图放置
的生产者。如果队列为空,BlockingQueue
将始终阻止使用者
这允许您删除队列上旋转并等待项目的所有自定义逻辑
使用Java 8 lambdas的一个简单示例如下所示:
public static void main(String[] args) throws Exception {
final BlockingQueue<String> q = new LinkedBlockingQueue<>();
final ExecutorService executorService = Executors.newFixedThreadPool(4);
final Runnable consumer = () -> {
while (true) {
try {
System.out.println(q.take());
} catch (InterruptedException e) {
return;
}
}
};
executorService.submit(consumer);
final Stream<Runnable> producers = IntStream.range(0, 5).mapToObj(i -> () -> {
final Random random = ThreadLocalRandom.current();
while (true) {
q.add("Consumer " + i + " putting " + random.nextDouble());
try {
TimeUnit.MILLISECONDS.sleep(random.nextInt(2000));
} catch (InterruptedException e) {
//ignore
}
}
});
producers.forEach(executorService::submit);
}
publicstaticvoidmain(字符串[]args)引发异常{
final BlockingQueue q=新的LinkedBlockingQueue();
final ExecutorService ExecutorService=Executors.newFixedThreadPool(4);
最终可运行消费者=()->{
while(true){
试一试{
System.out.println(q.take());
}捕捉(中断异常e){
返回;
}
}
};
执行器服务。提交(消费者);
最终流生产者=IntStream.range(0,5).mapToObj(i->()->{
final Random Random=ThreadLocalRandom.current();
while(true){
q、 添加(“消费者”+i+“放置”+random.nextDouble());
试一试{
时间单位.毫秒.睡眠(random.nextInt(2000));
}捕捉(中断异常e){
//忽略
}
}
});
producers.forEach(executorService::submit);
}
消费者
阻塞阻塞队列。采取
方法,一旦有可用的项目,它将被唤醒并打印该项目。如果没有项目,线程将被挂起-允许物理CPU执行其他操作
producer
各自使用add
将字符串推送到队列中。由于队列是无界的,add
将始终返回true。如果消费者
可能有积压的工作,您可以绑定队列并使用put
方法(抛出InterruptedException
因此需要try..catch
这就是为什么使用add
更容易的原因)-这将自动创建流控制。您没有使用同步队列
或线程安全的队列
,因此您有竞争危险。您使用LinkedList
表明您对这一事实缺乏了解(有点可怕)。在尝试处理更多的线程化代码之前,您可能需要阅读更多关于线程和线程安全的内容
您必须手动同步或使用JDK提供的现有实现之一。生产者/消费者模式通常使用BlockingQueue
实现之一实现
如果队列已满,则大小有界的阻塞队列
将阻止试图放置
的生产者。如果队列为空,BlockingQueue
将始终阻止使用者
这允许您删除队列上旋转并等待项目的所有自定义逻辑
使用Java 8 lambdas的一个简单示例如下所示:
public static void main(String[] args) throws Exception {
final BlockingQueue<String> q = new LinkedBlockingQueue<>();
final ExecutorService executorService = Executors.newFixedThreadPool(4);
final Runnable consumer = () -> {
while (true) {
try {
System.out.println(q.take());
} catch (InterruptedException e) {
return;
}
}
};
executorService.submit(consumer);
final Stream<Runnable> producers = IntStream.range(0, 5).mapToObj(i -> () -> {
final Random random = ThreadLocalRandom.current();
while (true) {
q.add("Consumer " + i + " putting " + random.nextDouble());
try {
TimeUnit.MILLISECONDS.sleep(random.nextInt(2000));
} catch (InterruptedException e) {
//ignore
}
}
});
producers.forEach(executorService::submit);
}
publicstaticvoidmain(字符串[]args)引发异常{
final BlockingQueue q=新的LinkedBlockingQueue();
final ExecutorService ExecutorService=Executors.newFixedThreadPool(4);
最终可运行消费者=()->{
while(true){
试一试{
System.out.println(q.take());
}捕捉(中断异常e){
返回;
}
}
};
苏先生