【问题标题】:Java Multithreading: How to use multi-threading in different ArrayList containing record info?Java多线程:如何在包含记录信息的不同ArrayList中使用多线程?
【发布时间】:2023-04-03 14:35:01
【问题描述】:

我从数据库中检索了 50000 个数据并将它们存储到 arraylist。我将arraylist分成两半,说250000存储在ArrayList1(偶数行)和其他25000 ArrayList2(奇数行)中。

现在,我需要使用多线程来处理这些,以便一次处理所有 50,000 条记录。主要目的是加快交易速度。

问题是userList 变得太重并且需要时间。

如何实现 ExecutorService 来加速?

希望尽快收到您的建议。

List<String[]> userList = new ArrayList<String[]>();
void getRecords()
{
    String [] props=null;
    while (rs.next()) {
        props = new String[2];
        props[0] = rs.getString("useremail");
        props[1] = rs.getString("active");
        userList.add(props);
        if (userList.size()>0) sendEmail();   
    }
}

void sendEmail()
{
    String [] user=null;
    for (int k=0; k<userList.size(); k++) 
    { 
        user = userList.get(k);
        userEmail = user[0];         
        //send email code
    }
}

提前致谢。

【问题讨论】:

  • 我假设您的意思是 25000 和 25000 各。 ;)

标签: java multithreading arraylist


【解决方案1】:

有一种更简单的方法:生产者-消费者。将所有项保留在一个列表中,并定义一个封装数据项的处理任务:

class Task implements Runnable {
     private Object data;

     public Task(Object data) {
         this.data = data;
     }

     public void run() {
        // process data
     }
}

创建一个线程池并将任务一一提供给它:

ExecutorService exec = Executors.newFixedThreadPool(4); // 4 threads
for(Object obj: itemList) {
    exec.submit(new Task(obj));
}

exec.shutdown();
exec.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS);

现在您有了并行执行和负载平衡 (!!!),因为线程在完成之前的任务时按需执行工作。通过将数组拆分为连续的部分,您无法获得此保证。

【讨论】:

  • 我会使用这种方法。此外,我认为没有任何理由在开始处理之前等待所有记录都被提取到数组中。从结果集中读取时,您可以开始将项目提交到队列。
【解决方案2】:

我会为每个线程创建一个 ArrayList。这样每个线程只读取一个列表,不会出现多线程问题。

ExecutorService service = ...


List<Work> workList = ...

int blockSize = (workList.size() + threads - 1)/threads;
for(int i = 0; i < threads;i ++) {
   int start = i * blockSize;
   int end = Math.min((i + 1) * blockSize, workList.size());
   final List<Work> someWork = work.subList(start, end);
   service.submit(new Runnable() {
       public void run() {
           process(someWork);
       }
   });
}

您可以使用任意数量的线程,但我建议使用可以提高性能的最小数量。

【讨论】:

  • 我有两种方法 1. getRecords(), 2. sendEmail().. 所以,getRecords 从数据库中检索信息并将它们存储到 Arraylist。如果 arraylist>0.. 调用 sendEmail 方法。但是拥有一个 ArrayList 会导致系统运行缓慢并且花费太多时间。我想要做的是将 ArrayList 分成两半,然后实现多线程以加快程序速度。谢谢。
  • 因此您可以使用 subList(from, to) 将 ArrayList 一分为二,并在传递给 ExecutorService 的两个任务中处理它们。您甚至可以将其拆分为更多方式,因为您有这么多。例如10 个或更多。
【解决方案3】:

我不知道您为什么将列表分成两个列表。为什么不将它们合二为一,并运行两个线程——一个处理偶数行,一个处理奇数行?

无论如何,请查看Java Executor 框架。它允许您轻松编写作业并提交它们以供运行(使用线程池、调度它们等)。鉴于执行程序框架可以处理任意数量的线程,我会更智能地拆分您的工作负载(可能分成“n”个元素的子列表)并确定(通过更改作业/线程的数量)在您的特定场景中哪个配置运行速度最快.

【讨论】:

  • 偶数/奇数存在错误共享问题。正如您接下来建议的那样,将子列表偏移排队到线程池会更好。
【解决方案4】:

我会使用Queue 而不是List,可能是ConcurrentLinkedQueue。这应该是线程安全的,因此允许来自不同线程的并发访问。

【讨论】:

    猜你喜欢
    • 2018-02-26
    • 1970-01-01
    • 2018-05-17
    • 2014-07-14
    • 2016-05-31
    • 2015-11-03
    • 2014-09-14
    • 2012-11-22
    • 2016-11-06
    相关资源
    最近更新 更多