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.

有帮助吗?

解决方案

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.

其他提示

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.

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.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top