1

I'm trying to create a multithreaded application in Java using ExecutorService thread pools. The application basically queries a third party service for data about a given keyword. Since I have many keywords and each request takes some time to generate, I would like to query the service in parallel. The requests are made through a ServiceHandler object which takes care of authentication and parsing the results out.

In my initial implementation, I create a new Callable for each keyword and creates a new ServiceHandler object to query the service. For some reason, this runs faster than sharing a singleton ServiceHandler object across all Callable. However, with large input data sets, I'm running into memory issues because it is creating new objects for each input keyword.

Is there a way to still use ExecutorService but only create a distinct instance of ServiceHandler for each worker thread? For example, if I have 1000 keywords and a fixed pool of 20 threads, I want to only create one ServiceHandler for each thread (20 total) while still having one Callable for each keyword(1000 total).

I tried adding a static ThreadLocal object to each Callable objects that returns a new ServiceHandler in its initialValue() , but it seems like only one ServiceHandler is being created? I can post my code for this, but I'm not even sure if this is the right approach.

Yiling
  • 99
  • 2
  • 9

3 Answers3

1

Yes, there is a way to create only one instance of object per thread, you should use ThreadLocal<ServiceHandler> and declare it as a static field. This would create only one instance of object per thread. You can check http://docs.oracle.com/javase/6/docs/api/java/lang/ThreadLocal.html this for official documentation.

Desert
  • 2,293
  • 15
  • 16
  • I tried this and added a new a static volatile instanceCount variable in ServiceHandler. When I increment that variable in ServiceHandler's constructor and print it out, I always get 1, which seems like I'm only creating a single instance? – Yiling Jun 27 '13 at 22:57
0

I think this is a producer-consumer problem. You have a BlockingQueue which may contain as many keywords as you like, and a pool of 20 consumer/service threads.

The service threads work like this:

while (true) {
   Keyword k = queue.pop();
   process(k);
}

Your producer thread just fills up the queue with the keywords that you want to process and one of the service threads will take care of it.

Csaba
  • 340
  • 1
  • 3
  • 16
  • It basically is, but I would like to use ExecutorService because it lets me create a main class that reads in input, creates the Thread Pool, and then writes out the output once the results are returned from the service. If I create separate service threads, I sort of have to implement my own ExecutorService type framework. – Yiling Jun 27 '13 at 23:09
0

I figure out what my particular issue is. The correct solution is to use a ThreadLocal object, but the issue with my implementation was that I was calling the ThreadLocal.get() method when I was constructing each Callable. Since the construction takes place in the main Thread and NOT the ExecutorService's worker threads, I was always getting the same ServiceHandler instance, which made it perform similar to a singleton.

Once I moved the call to get() to the Callable's call() method, then the correct execution happens.

Yiling
  • 99
  • 2
  • 9