1

我正在尝试使用 ExecutorService 线程池在 Java 中创建多线程应用程序。该应用程序基本上查询第三方服务以获取有关给定关键字的数据。由于我有很多关键字并且每个请求都需要一些时间来生成,我想并行查询服务。请求是通过 ServiceHandler 对象发出的,该对象负责身份验证和解析结果。

在我的初始实现中,我为每个关键字创建一个新的 Callable 并创建一个新的 ServiceHandler 对象来查询服务。出于某种原因,这比在所有 Callable 中共享单个 ServiceHandler 对象运行得更快。但是,对于大型输入数据集,我遇到了内存问题,因为它正在为每个输入关键字创建新对象。

有没有办法仍然使用 ExecutorService 但只为每个工作线程创建一个不同的 ServiceHandler 实例?例如,如果我有 1000 个关键字和 20 个线程的固定池,我只想为每个线程创建一个 ServiceHandler(总共 20 个),同时仍然为每个关键字创建一个 Callable(总共 1000 个)。

我尝试向每个 Callable 对象添加一个静态 ThreadLocal 对象,该对象在其 initialValue() 中返回一个新的 ServiceHandler ,但似乎只创建了一个 ServiceHandler ?我可以为此发布我的代码,但我什至不确定这是否是正确的方法。

4

3 回答 3

1

是的,有一种方法可以为每个线程只创建一个对象实例,您应该使用ThreadLocal<ServiceHandler>并将其声明为静态字段。这将只为每个线程创建一个对象实例。您可以查看http://docs.oracle.com/javase/6/docs/api/java/lang/ThreadLocal.html以获取官方文档。

于 2013-06-27T22:29:44.047 回答
0

我弄清楚我的具体问题是什么。正确的解决方案是使用 ThreadLocal 对象,但我实现的问题是我在构造每个 Callable 时调用了 ThreadLocal.get() 方法。由于构造发生在主线程而不是 ExecutorService 的工作线程中,所以我总是得到相同的 ServiceHandler 实例,这使得它的执行类似于单例。

一旦我将对 get() 的调用移至 Callable 的 call() 方法,就会发生正确的执行。

于 2013-06-28T00:18:04.637 回答
0

我认为这是一个生产者-消费者问题。您有一个 BlockingQueue,它可能包含任意数量的关键字,以及一个包含 20 个使用者/服务线程的池。

服务线程的工作方式如下:

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

您的生产者线程只是用您要处理的关键字填充队列,其中一个服务线程将处理它。

于 2013-06-27T22:31:26.213 回答