Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/342.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 队列工作线程停止工作,线程安全问题?_Java_Multithreading_Thread Safety - Fatal编程技术网

Java 队列工作线程停止工作,线程安全问题?

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,但这并不

我想先介绍一下我的问题

我有几个WorkingReads,它们接收字符串,处理字符串,然后将处理后的字符串发送到全局队列,如下所示:

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){
返回;
}
}
};
苏先生