我正在研究多年来我的第一个多线程应用程序。我遇到的问题是我需要同时执行两个方法。这是我的引擎类:
public class ThreadPoolEngine {
// create BlockingQueue to put fund transfer objects
private BlockingQueue<GlobalSearchRequest> searchQueue;
public ThreadPoolExecutor executor;
private HashMap<String, GlobalSearchProcessorCallable> callableMap;
private ArrayList<Future<Integer>> futurList;
Logger logger = Logger.getLogger(ThreadPoolEngine.class);
private Integer gthreadCount;
private Integer gjobPerThread;
public ThreadPoolEngine(Integer threadCount, Integer jobPerThread) {
gthreadCount = threadCount;
gjobPerThread = jobPerThread;
// create a thread pool with the entered no of threads
executor = new HammerThreadPoolExecutor(threadCount, threadCount, 0L,
TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>());
searchQueue = new ArrayBlockingQueue<GlobalSearchRequest>(jobPerThread);
callableMap = new HashMap<String, GlobalSearchProcessorCallable>();
// create list to store reference to Future objects
futurList = new ArrayList<Future<Integer>>();
}
public void createAndSubmitTasks() {
// create Callables
for (int i = 0; i < gthreadCount; i++) {
GlobalSearchProcessorCallable callable1 = new GlobalSearchProcessorCallable(
"SearchProcessor_" + i, searchQueue);
callableMap.put(callable1.getThreadName(), callable1);
// submit callable tasks
Future<Integer> future;
future = executor.submit(callable1);
futurList.add(future);
}
}
public void populateSearchQueue() throws InterruptedException {
// put orderVO objects in BlockingQueue
KeywordFactory key = KeywordFactory.getInstance();
for (int i = 0; i < gjobPerThread*gthreadCount; i++) {
// this method will put SearchRequest object in the order queue
try {
searchQueue.put(new GlobalSearchRequest(key.getRandomPhrase(3)));
} catch (KeywordNoDataFileException e) {
e.printStackTrace();
}
}
}
public void printProcessorStatus() throws InterruptedException {
// print processor status until all orders are processed
while (!searchQueue.isEmpty()) {
for (Map.Entry<String, GlobalSearchProcessorCallable> e : callableMap
.entrySet()) {
logger.debug(e.getKey() + " processed order count: "
+ e.getValue().getProcessedCount());
}
Thread.sleep(1000);
}
}
public void shutDown(boolean forceShutdown) {
if (!forceShutdown) {
// shutdown() method will mark the thread pool shutdown to true
executor.shutdown();
logger.debug("Executor shutdown status " + executor.isShutdown());
logger.debug("Executor terninated status "
+ executor.isTerminated());
// Mark threads to return threads gracefully.
for (Map.Entry<String, GlobalSearchProcessorCallable> orderProcessor : callableMap
.entrySet()) {
orderProcessor.getValue().setRunning(false);
}
} else {
for (Future<Integer> f : futurList) {
f.cancel(true);
}
// shutdown() method will mark the thread pool shutdown to true
executor.shutdownNow();
}
}
public void printWorkersResult() {
for (Future<Integer> f : futurList) {
try {
Integer result = f.get(1000, TimeUnit.MILLISECONDS);
logger.debug(f + " result. Processed orders " + result);
} catch (InterruptedException e) {
logger.error(e.getMessage(), e);
} catch (ExecutionException e) {
logger.error(e.getCause().getMessage(), e);
} catch (TimeoutException e) {
logger.error(e.getMessage(), e);
} catch (CancellationException e) {
logger.error(e.getMessage(), e);
}
}
}
}
好吧,我有一个实例化这个类的主类,并在这个类上调用两个方法,populateSearchQueue和createAndSubmitTasks来运行我的worker类并处理搜索队列中的项。
问题所在 populateSearchQueue方法可能需要花费很长时间才能构建(我将使用一次10亿个查询来破坏系统)并且可能需要大量内存。在java中有一种方法,我的主类可以同时调用populateSearchQueue和createAndSubmitTasks,这样工作线程可以开始处理队列,而它仍然是由populateSearchQueue方法构建的吗?
答案 0 :(得分:1)
我实际上解决了它。我再次阅读我的代码并意识到创建线程池需要很少的时间。因此,调用创建线程池的createAndSubmitTasks
,并为每个分配一个等待执行某些操作的工作类。当该方法完成后,我现在拥有1000个线程池,无所事事。然后,在我调用populateSearchQueue
的那一刻,那些闲置了几毫秒的工作线程转移到下一个方法,现在开始从队列中抓取工作,我得到了我想要的结果。将内容放入队列的方法是在工作线程从该队列中抓取作业并运行它们的同时进行处理。
所以我颠倒了我调用方法的顺序。这是一件美丽的事情。