user1651714
user1651714

Reputation: 1

Java Multithreading: How to use multi-threading in different ArrayList containing record info?

I retrieved 50000 data from database and stored them to arraylist. I split the arraylist into half saying 250000 stored in ArrayList1 (even rows) and other 25000 ArrayList2 (odd rows).

Now, I need to use multi-threading in order to process these such that all 50,000 records are processed at a time. Main aim is to speed up the transaction.

The problem is userList gets too heavy and takes time.

How can I implement ExecutorService to speed up?

Hoping to receive your suggestions asap.

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
    }
}

Thanks in advance.

Upvotes: 0

Views: 5910

Answers (4)

Peter Lawrey
Peter Lawrey

Reputation: 533500

I would create an ArrayList for each Thread. That way each thread only reads one list and you won't have a multi-threading issue.

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);
       }
   });
}

You can use any number of threads, but I suggest using the smallest number which gives you a performance increase.

Upvotes: 2

Sean Patrick Floyd
Sean Patrick Floyd

Reputation: 298898

I would use a Queue instead of a List, probably a ConcurrentLinkedQueue. That should be thread safe and thus allow concurent access from different threads.

Upvotes: 0

Tudor
Tudor

Reputation: 62439

There's a simpler approach: producer-consumer. Leave all items in a single list and define a processing task that encapsulates a data item:

class Task implements Runnable {
     private Object data;

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

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

Create a thread pool and feed it the tasks one by one:

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);

Now you have parallel execution and load balancing (!!!) since the threads execute work on-demand as they finish previous tasks. By splitting the array into contiguous sections you don't have this guarantee.

Upvotes: 2

Brian Agnew
Brian Agnew

Reputation: 272257

I don't know why you've split the list into two lists. Why not keep them in one, and run two threads - one processing the even rows, one processing the odd rows ?

Regardless, check out the Java Executor framework. It allows you to easily write jobs and submit them for running (using thread pools, schedulign them etc.). Given that the executor framework can handle arbitrary numbers of threads, I would split your workload more intelligently (perhaps into sublists of 'n' elements) and determine (via changing the number of jobs/threads) which configuration runs the fastest in your particular scenario.

Upvotes: 0

Related Questions