【问题标题】:Writing to multiple files in a multithreaded way in java在java中以多线程方式写入多个文件
【发布时间】:2016-05-03 11:52:55
【问题描述】:

我有一个 Java 应用程序,我需要在其中使用多线程。 我有一个ID's 列表,它是存储在 DynamoDB 中的表的主键。

说,清单是:

| ID_1 | ID_2 | ID_3 | ID_4|.......| ID_n|

现在我希望多个线程读取这些ID's 并对每个 ID 执行以下操作:

  1. 每个线程都应获取一个 ID 并查询 DynamoDB 表(有两个以 ID 为主键的 dynamo DB 表)

  2. 查询每个 Dynamo DB 表的结果应存储在单独的文件中。

基本上,Thread_1 应该选择一个 ID,比如 ID_1,它应该查询 DynamoDB 表 DDB_1DDB_2。查询DDB_1的结果应该进入File1DDB_2的结果应该进入File_2。这需要对所有线程进行。最后,当所有线程都完成执行后,我应该有两个文件File_1File_2,其中包含来自所有线程的查询结果。

我想出了一个解决方案,让所有生产者线程(从 Dynamo DB 获取查询结果的线程)将查询结果排队到写入文件的单个消费者线程,例如 File_1。同样,所有生产者线程写入第二个队列,第二个消费者线程写入File_2

您觉得上述方法有什么缺陷吗?在这种情况下,有没有更好的方法来应用多线程?

【问题讨论】:

  • 请在此处发布您的代码...尝试发布MCVE
  • 我目前正在决定设计。一旦找到可能的解决方案,我将开始实施它。需要检查这是否是一个可行的解决方案,或者有更好的方法可以尝试!

标签: java multithreading


【解决方案1】:

这就是你想要达到的目标:-

ID_1 -> Thread1 -> Query DB1 ->  ConsumerSingleton -> Write data to File 1
                -> Query DB2 ->  ConsumerSingleton -> Write data to File 2
ID_2 -> Thread2 -> Query DB1 ->  ConsumerSingleton -> Write data to File 1
                -> Query DB2 ->  ConsumerSingleton -> Write data to File 2

ID_3 -> Thread3 -> Query DB1 ->  ConsumerSingleton -> Write data to File 1
                -> Query DB2 ->  ConsumerSingleton -> Write data to File 2
..
..  
ID_N -> ThreadN -> Query DB1 ->  ConsumerSingleton -> Write data to File 1
                -> Query DB2 ->  ConsumerSingleton -> Write data to File 2

由于您使用的是单个消费者对象,因此您不必处理 file1 和 file2 的同步写入操作。但是你必须同步 线程将结果转储到消费者集合的操作/方法。您可以使用 ConcurrentHashMap 从您的消费者类中的不同线程收集结果,这是线程安全的。

此外,由于您将根据唯一 id 的行级别锁定从 DB1 和 DB2 读取行,因此在多个线程尝试访问时不应发生。如果不是这种情况,则可能会发生 2 个线程尝试读取具有相同 ID 争用的行。

【讨论】:

    【解决方案2】:

    如果我理解正确,您需要 2 个线程,每个线程查询一个数据库表并将结果发布到一个文件中。见下文。

    APPLICATION
    |
    |-->THREAD --> DB_1 --> file1
    |
    |-->THREAD --> DB_2 --> file2
    

    首先这应该很好,你不是在读取和写入相同的数据,这意味着这是线程安全的。你想要这样做的方式是为每个线程创建一个类(只是一个例子)。通过扩展 runnable 来做到这一点。然后将所有用于连接数据库的代码放在 run 方法中。长示例:http://www.tutorialspoint.com/java/java_multithreading.htm

    简短示例

    class Thread1 implements Runnable {
    
        public void run() {
            Connect/write
        } 
    }
    

    使用调用

    Thread1 t = new Thread1();
    t.start();
    

    只要您在其中一个线程中阅读 ID 时不编辑 ID,这应该可以正常工作。

    使用同步

    这会将方法锁定到单个线程,例如,当写入同一个文件时,这是必要的,因为线程会相互中断。

    public synchronized void write(text, file1, file2){
    
    }
    

    在你的线程中调用它就像一个正常的方法。这并不能保证线程访问这些方法的顺序,在本例中是先到先得。

    【讨论】:

    • 我想你误解了我的意思。我希望 k 线程运行,每个线程查询两个 dynamo db 表并将结果发布到两个单独的文件中,每个文件对应一个 DDB 表。所以,我的 Thread_1 写入两个文件,FILE1 和 FILE2,Thread_2 也写入这两个文件.....Thread_k 也写入这些文件......那应该是什么方法呢?谢谢
    • 如果你想这样做,你必须将你的写入同步到文件中,这只需将同步添加到你调用的写入文件的方法中。如果您不这样做,您的线程将在编写过程中相互中断,还要注意这可能不会按照您期望的顺序给出结果。这是假设以下情况。应用 | |-->线程 --> DB_1 --> 同步方法(file1, file2) | |-->THREAD --> DB_2 --> SYNCHRONIZED 方法(file1, file2)
    【解决方案3】:

    您觉得上述方法有什么缺陷吗?

    我一个也找不到。但当然,我只能根据您对算法的高级描述进行评论。实现它的方式有对也有错。

    在这种情况下有没有更好的方法来应用多线程?

    很难说。但我想不出任何明显更好的替代方案。 (毫无疑问)有替代方案,但您可以客观地确定哪个最佳1的唯一方法是实施各种替代方案并对其进行基准测试。

    请注意,此应用程序的瓶颈可能是:

    • DynamoDB 查询的有效吞吐量
    • 将结果写入文件的速率

    (可能前者将占主导地位。)由于两者都将受到“外部”因素(例如磁盘 I/O、网络、数据库 CPU 负载)的限制,您很可能需要“调整”数字您使用的工作线程数。


    1 - 我假设您的意思是吞吐量最高的那个。

    【讨论】:

      猜你喜欢
      • 2020-04-14
      • 2015-08-12
      • 2020-04-14
      • 2016-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多