需要 Java 多线程方面的帮助

我有一个案例如下:

有很多记录。 每条记录大约有 250 个字段。 每个字段都需要根据预定义的规则进行验证。

所以我定义了一个类 FieldInfo 来表示每个字段:

public class FieldInfo {
    private String name;
    private String value;
    private String error_code;
    private String error_message;

    // ignore getters and setters
} 

一个类 Record 来表示一条记录:

public class Record {
    List<FieldInfo> fields;

    // omit getter and setter here
}

以及规则接口和类:

public interface BusinessRule {
    // validating one field needs some other fields' value in the same record. So the list of all fields for a certain record passed in as parameter 
    public FieldInfo validate(List<FieldInfo> fields);
}

public class FieldName_Rule implements BusinessRule {

    public FieldInfo validate(List<FieldInfo> fields) { 
    // will do 
    // 1. pickup those fields required for validating this target field, including this target field
    // 2. performs validation logics A, B, C... 

    // note: all rules only read data from a database, no update/insert operations. 
    }
}

用户可以一次提交 5000 条或更多记录进行处理。 性能要求很高。 我正在考虑为提交的多个线程,例如5000条记录(意味着一个线程运行多个记录),并且在每个线程中,在每个记录上分叉另一个多个线程以运行规则。

但不幸的是,这种嵌入式多线程在我的情况下总是消亡。

以下是上述解决方案的一些关键部分:

public class BusinessRuleService {

    @Autowired
    private ValidationHandler handler;

    public String process(String xmlRequest) {
        List<Record> records = XmlConverter.unmarshall(xmlRequest).toList();
        ExecutorService es = Executors.newFixedThreadPool(100);
        List<CompletableFuture<Integer> futures = 
                records.stream().map(r->CompletableFuture.supplyAsync(()-> handler.invoke(r), es)).collect(Collectors.toList());
        List<Integer> result = future.stream().map(CompletableFuture::join).collect(Collectors.toList());
        System.out.println("total records %d processed.", result.size());
        es.shutdown();
        return XmlConverter.marshallObject(records);
    }
}

@Component
public class ValidationHandlerImpl implements ValidationHandler {

    @Autowired
    private List<BusinessRule> rules;

    @Override
    public int invoke(Record record) {

        ExecutorService es = Executors.newFixedThreadPool(250);
        List<CompletableFuture<FieldInfo> futures = 
                rules.stream().map(r->CompletableFuture.supplyAsync(()-> r.validate(record.getFields()), es)).collect(Collectors.toList());
        List<FieldInfo> result = future.stream().map(CompletableFuture::join).collect(Collectors.toList());
        System.out.println("total records %d processed.", result.size());
        es.shutdown();
        return 0;
    }
}

工作流程是:用户以 xml 字符串格式提交记录列表。 应用程序端点之一在 BusinessRuleService 对象中启动流程方法。 该过程使用 CompletableFuture 来组合任务并将任务提交给一个 ExecutorService,该服务具有一个大小为 100 的线程池。 CompletableFuture 列表中的每个任务然后启动 ValidationHandler 对象。 ValidationHandler 对象组成另一个 CompletableFuture 任务,并将任务提交给另一个池大小与规则列表大小相同的 ExecutorService。

上面的解决方案是否合适?

注意:我目前的解决方案是:对提交的记录进行顺序处理。 每条记录并行处理 250 条规则。 使用这个方案,5000条记录需要2个多小时。 这种糟糕的表现是企业不能接受的。

我对并发/多线程编程很陌生。 非常感谢各种帮助!

#1楼 票数:0

这是众所周知的“单生产者-多消费者”模式。 经典的解决方案是创建一个BlockingQueue<Record> queue ,并按照读取的速度将记录放在那里。 在队列的另一端,一些工作线程从queue读取记录并处理它们(在我们的例子中,验证字段):

class ValidatingThread extends Tread {
   BlockingQueue<Record> queue;
   FieldName_Rule validator = new FieldName_Rule();

   public Validator (BlockingQueue<Record> queue) {
      this.queue = queue;
   }

   public void run() {
      Record record = queue.take();
      validator.validate(collectFields(record));
   }
}

最佳线程数等于Runtime.getRuntime().availableProcessors() 一开始就启动它们,不要使用“嵌入式多线程”。 在处理完所有记录后如何停止线程的任务留作学习任务。

  ask by Min Jiang translate from so

未解决问题?本站智能推荐:

4回复

Java多线程优化

在我的程序中,我尝试了解如何使用ExecutorService优化程序。 由于某些原因,它在两个Urls上卡住了一点。 http://sjsu.edu/和https://paypal.com 。 当位于这两个位置上时,它不会继续执行其他URL。 即使两个域的响应速度不够快,其他三个可用
2回复

多线程Java

在我的程序中,我基本上有一个类似于的方法: 所以基本上我有一个图像文件夹,我比较所有图像组合...所以比较图像1与所有图像,然后图像2 ......等等。 我的问题是在搜索什么图像匹配时,需要很长时间。 我试图多线程这个过程。 有没有人知道如何做到这一点?
3回复

java多线程ExecutorService

我正在尝试为Lucene索引创建多线程。 假设我有一个从101到999的数字列表。我想要实现的是将这个列表分成不同的组,每个组由不同的线程处理。 我可以将其分区到不同的组,但是,在运行多线程时,在这种情况下,所有线程仅采用第一个分区(l [0])。 例如,上面的代码创建了3个线程(t1,
2回复

Java多线程问题

1):单线程应用程序在用户的CPU上只会使用1个线程吗? 分配更多线程会使用多个CPU内核吗? 如果声明的线程数超过了用户CPU的数量,会发生什么? 2):只要您的方法没有同步问题或其他问题,对每个方法创建新线程是否会对性能造成不利影响? 3):我在做游戏,有时候收集垃圾时会有明显的
1回复

Java多线程渲染,如何优化

我正在开发一个分形渲染软件。 基本设置是我有一个很大的二维数组(图片),其中值递增。 简单的渲染过程是 这很容易并行化。 仅有几个线程可以同时执行此操作,因为每个线程(很有可能)同时使用不同的像素,即使数组中存在更新冲突,也可以。 数组在线程之间共享! 但是,为了跟踪已完成的I
3回复

Java多线程-最佳实践

我很难理解教师的多线程方法。 好吧,在展示我们的两个例子之前,我必须说他正在教一些新手(包括我,我想^。^)所以他可能选择了一种易于理解的多线程方法。 另外,我没有参观他的课程,但是我的脚本上写着以下内容: 他正在做这样的多线程: 我觉得这样做比较干净: 不要理会我为什么使用大小
1回复

Java多线程:线程应访问列表

我正在运行五个线程,并且我有一个对象列表(我独立于线程进行初始化)。 列表中的对象使用布尔值作为标志,所以我知道它们是否已经被另一个线程处理过。 此外,我的线程有一个整数作为它的“ID”(所以你知道哪个线程当前正在工作)。 问题:第一个参与 for 循环的线程将处理列表中的所有对象,但我希望线程交替
1回复

是Java多线程可以优化多个文件的写入

我有一个 400+ GB 的文件,例如: 我希望根据 ID 将文件分块以获得更快的数据检索,如下所示: 我的代码工作正常,但无论我使用什么编写器来关闭循环结束,它至少需要 159,206 毫秒才能完成 0.001% 的文件创建。 在这种情况下,多线程可以成为降低时间复杂度的一种选择(就像一次写入 1