Java Kafka流处理器线程安全?

Java Kafka流处理器线程安全?,java,multithreading,apache-kafka-streams,Java,Multithreading,Apache Kafka Streams,我知道之前有人问过这个问题: 但这对我来说很奇怪。根据文档(或者我可能遗漏了什么),每个分区都有一个任务,这意味着处理器的不同实例,每个任务都由不同的线程执行。但当我测试它时,我发现不同的线程可以得到不同的处理器实例。因此,如果您想在处理器中保持任何内存状态(老式方式),您必须锁定吗 示例代码: public class SomeProcessor extends AbstractProcessor<String, JsonObject> { private final St

我知道之前有人问过这个问题:

但这对我来说很奇怪。根据文档(或者我可能遗漏了什么),每个分区都有一个任务,这意味着处理器的不同实例,每个任务都由不同的线程执行。但当我测试它时,我发现不同的线程可以得到不同的处理器实例。因此,如果您想在处理器中保持任何内存状态(老式方式),您必须锁定吗

示例代码:

public class SomeProcessor extends AbstractProcessor<String, JsonObject> {

   private final String ID = UUID.randomUUID().toString();

   @Override
   public void process(String key, JsonObject value) {
     System.out.println("Thread id: " + Thread.currentThread().getId() +" ID: " + ID);
公共类SomeProcessor扩展了AbstractProcessor{
私有最终字符串ID=UUID.randomUUID().toString();
@凌驾
公共void进程(字符串键、JsonObject值){
System.out.println(“线程id:+Thread.currentThread().getId()+”id:+id”);
输出:

螺纹id:88 id:26b11094-a094-404b-b610-88b38cc9d1ef

螺纹id:88 id:c667e669-9023-494b-9345-236777e9dfda

螺纹id:88 id:c667e669-9023-494b-9345-236777e9dfda

螺纹id:90 id:0a43ecb0-26f2-440d-88e2-87e0c9cc4927

螺纹id:90 id:c667e669-9023-494b-9345-236777e9dfda

螺纹id:90 id:c667e669-9023-494b-9345-236777e9dfda


有没有办法强制每个实例执行线程?

每个实例的线程数是一个配置参数(
num.stream.threads
,默认值为
1
)。因此,如果启动单个
KafkaStreams
实例,则会得到
num.stream.threads
线程

public class SomeProcessor extends AbstractProcessor<String, JsonObject> {

   private final String ID = UUID.randomUUID().toString();

   @Override
   public void process(String key, JsonObject value) {
     System.out.println("Thread id: " + Thread.currentThread().getId() +" ID: " + ID);
任务以并行单元(基于您的输入主题分区)分割工作,并将分配给线程。因此,如果您有多个任务和一个线程,则所有任务都将分配给该线程。如果您有两个线程(合计所有
KafkaStreams
实例),则每个线程执行大约50%的任务

注意:由于Kafka Streams应用程序本质上是分布式的,因此,如果您使用多个线程运行单个
KafkaStreams
实例,或者使用每个线程运行多个
KafkaStreams
实例,则没有区别。任务将分布在应用程序的所有可用线程上


如果要在任务之间共享任何数据结构,并且您有多个线程,则您有责任同步对此数据结构的访问。请注意,任务到线程的分配可能会在运行时更改,因此,所有访问都必须同步。但是,不建议使用此模式,因为它限制了可伸缩性ty.您应该在设计程序时不使用共享数据结构!主要原因是,您的程序通常分布在多台机器上,因此不同的
KafkaStreams
实例无论如何都无法访问共享数据结构。共享数据结构只能在单个JVM中工作,但使用单JVM防止应用程序横向扩展。

谢谢@matthias-j-sax的回复。我实际上知道这些选项。问题是我不会将流写为“非线程安全”并强制使用一个线程,因为这是一种不好的做法。我只是假设Kafka流将支持“线程安全”在进程/标点API上,类似于AKKA actor模式。但我想我错了。不管怎样,现在我明白了,我除了使用老式的锁定之外没有别的选择。感谢againHi@Mathias-j-sax-我们也遇到了这个问题-处理器的实例是否可能同时运行进程()和标点()在不同的线程上?这是不可能的。在单个线程中执行
process()
方法和注册的
标点符号。