Nis*_*ain 2 java multithreading executorservice
我正在尝试使用执行器接口实现多线程方法,其中我在主类中生成了多个线程
class Main
{
private static final int NTHREADS = 10;
public static void main(String[] args)
{
.........
String str = createThreads(document);
.............
}
public String createThreads(String docString)
{
........
.......
Map<String,String> iTextRecords = new LinkedHashMap<String, String>();
if(!iText.matches(""))
{
String[] tokenizedItext = iText.split("\\^");
ExecutorService executor = Executors.newFixedThreadPool(NTHREADS);
for(int index = 0 ;index < tokenizedItext.length;index++)
{
Callable<Map<String,String>> worker = null;
Future<Map<String,String>> map = null;
if(tokenizedItext[index].matches("^[0-9.<>+-= ]+$") || tokenizedItext[index].matches("^\\s+$"))
{
iTextRecords.put(tokenizedItext[index],tokenizedItext[index]);
}
else
{
worker = new MultipleDatabaseCallable(tokenizedItext[index],language);
map = executor.submit(worker);
try
{
iTextRecords.putAll(map.get());
}
catch(InterruptedException ex)
{
ex.printStackTrace(System.out);
}
catch(ExecutionException ex)
{
ex.printStackTrace(System.out);
}
}
}
executor.shutdown();
// Wait until all threads are finish
while (!executor.isTerminated())
{
}
}
}
Run Code Online (Sandbox Code Playgroud)
Callable类是
class MultipleDatabaseCallable implements Callable<Map<String,String>>
{
@Override
public Map<String, String> call() throws Exception {
System.out.println("Entering: "+Thread.currentThread().getName());
Map<String,String> map = new HashMap<String,String>();
for(int i =0;i<50000;i++)
{
for(int i1 = 0 ;i1<5000;i1++)
{
for(int i2 =0;i2 <500;i2++)
{
}
}
}
System.out.println("Exiting: "+Thread.currentThread().getName());
return map;
}
}
Run Code Online (Sandbox Code Playgroud)
我得到的输出是
Entering: pool-1-thread-1
Exiting: pool-1-thread-1
Entering: pool-1-thread-2
Exiting: pool-1-thread-2
Entering: pool-1-thread-3
Exiting: pool-1-thread-3
Entering: pool-1-thread-4
Exiting: pool-1-thread-4
Entering: pool-1-thread-5
Exiting: pool-1-thread-5
Entering: pool-1-thread-6
Exiting: pool-1-thread-6
Run Code Online (Sandbox Code Playgroud)
在查看输出时,似乎在调用方法中一次只有一个线程进入,而其他线程仅在前一个线程存在时才进入.但是,预计多个线程应该进入并执行call()方法.当我通过使NTHREADS = 1执行相同的程序时,它花费相同的时间,因为NTHREADS = 10
所以看起来应用程序运行和单线程应用程序一样好.请指出我在实现中做错了什么.
谢谢
你打电话的时候
map = executor.submit(worker);
Run Code Online (Sandbox Code Playgroud)
map在这种情况下返回的值是a Future.意味着它没有值,直到callable返回一个值.现在你打电话的时候
iTextRecords.putAll(map.get());
Run Code Online (Sandbox Code Playgroud)
会发生什么事情是当前线程阻塞(在里面map.get())等待callable返回(在另一个线程中).
因为map.get()在提交新的(每个)之前总是等待一个可调用的完成(每个),所以executor.submit()你强制执行你观察到的顺序执行.
为了并行执行任务,您必须在第一次调用get之前启动它们.你可以创建一个ArrayList<Future<Map<String,String>>> futures = ...然后做
futures.add(executor.submit(worker));
Run Code Online (Sandbox Code Playgroud)
提交任务(不需要map变量)并创建第二个循环(循环后for(int i ...)):
for(Future<Map<String,String>> f: futures) {
iTextRecords.putAll(f.get);
}
Run Code Online (Sandbox Code Playgroud)