为什么我的 JAVA 线程池没有节省时间?
Why my JAVA threadpool is not saving time?
我有这个简单的代码,但它并没有节省时间。 运行时间和使用单线程一样。怎么了?你能帮忙吗?我对此很陌生,如果问题太简单,我希望这个问题不会惹恼您。谢谢!
import java.util.Random;
import java.util.concurrent.Callable;
public class Work implements Callable<int[]>
{
int id;
int y;
public Work(int i)
{
id=i;
}
public int[] doit(){
Random rand = new Random();
y=rand.nextInt(10);
try {
Thread.sleep(y*1000); //1000 milliseconds is one second.
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
System.out.println(ex.getMessage());
}
int x[] = new int[2];
x[0]=id;
x[1]=y;
return x;
}
@Override
public int[] call() throws Exception
{
return doit();
}
}
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Driver
{
ArrayList<int[]> result=new ArrayList<int[]>() ;
public Driver()
{
}
public void doCalc(int n)
{
for (int i=0; i<n; i++) {
Work w = new Work(i);
int[] y = w.doit();
if (y != null) {
result.add(y);
}
}
int total=0;
for (int i=0; i< result.size(); i++) {
System.out.println("id = " + result.get(i)[0] + "; random number = "+ result.get(i)[1]);
total+=result.get(i)[1];
}
System.out.println("total = " + total);
}
public void doCalcThread(int n)
{
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i=0; i<n; i++) {
Work w = new Work(i);
Future<int[]> future =executor.submit(w);
int[] y;
try
{
y = future.get();
if (y != null) {
result.add(y);
}
} catch (InterruptedException | ExecutionException e)
{
e.printStackTrace();
}
}
executor.shutdown();
while (!executor.isTerminated()) {
}
System.out.println("Finished all threads");
int total=0;
for (int i=0; i< result.size(); i++) {
System.out.println("id = " + result.get(i)[0] + "; random number = "+ result.get(i)[1]);
total+=result.get(i)[1];
}
System.out.println("total = " + total);
}
/**
* @param args
*/
public static void main(String[] args)
{
Driver dr = new Driver();
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
cal = Calendar.getInstance();
System.out.println( "before " + sdf.format(cal.getTime()) );
//dr.doCalc(5);
dr.doCalcThread(5);
cal = Calendar.getInstance();
System.out.println( "after " + sdf.format(cal.getTime()) );
}
}
future.get();
是等待计算完成的阻塞操作。所以基本上你在你的循环中一次启动一个线程 - >没有任何并行性。这是错误的代码:
for (int i=0; i<n; i++) {
Work w = new Work(i);
Future<int[]> future =executor.submit(w);
int[] y;
try
{
y = future.get();
if (y != null) {
result.add(y);
}
} catch (InterruptedException | ExecutionException e)
{
e.printStackTrace();
}
}
所以基本上您需要将所有 Future<>
存储在列表中,并且在您提交所有这些之后开始调用它们的 get()
方法。这将允许任务 运行 并行。
就像 Svetlin Zarev 提到的,您的 future.get() 正在阻塞,但是如果您使用的是 java 8,我建议您查看 CompleteableFuture,因为您可以看到所有线程运行,并使用 CompleteableFuture.allOf() 检查它们是否全部完成,并在完成后添加结果
我有这个简单的代码,但它并没有节省时间。 运行时间和使用单线程一样。怎么了?你能帮忙吗?我对此很陌生,如果问题太简单,我希望这个问题不会惹恼您。谢谢!
import java.util.Random;
import java.util.concurrent.Callable;
public class Work implements Callable<int[]>
{
int id;
int y;
public Work(int i)
{
id=i;
}
public int[] doit(){
Random rand = new Random();
y=rand.nextInt(10);
try {
Thread.sleep(y*1000); //1000 milliseconds is one second.
} catch(InterruptedException ex) {
Thread.currentThread().interrupt();
System.out.println(ex.getMessage());
}
int x[] = new int[2];
x[0]=id;
x[1]=y;
return x;
}
@Override
public int[] call() throws Exception
{
return doit();
}
}
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class Driver
{
ArrayList<int[]> result=new ArrayList<int[]>() ;
public Driver()
{
}
public void doCalc(int n)
{
for (int i=0; i<n; i++) {
Work w = new Work(i);
int[] y = w.doit();
if (y != null) {
result.add(y);
}
}
int total=0;
for (int i=0; i< result.size(); i++) {
System.out.println("id = " + result.get(i)[0] + "; random number = "+ result.get(i)[1]);
total+=result.get(i)[1];
}
System.out.println("total = " + total);
}
public void doCalcThread(int n)
{
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i=0; i<n; i++) {
Work w = new Work(i);
Future<int[]> future =executor.submit(w);
int[] y;
try
{
y = future.get();
if (y != null) {
result.add(y);
}
} catch (InterruptedException | ExecutionException e)
{
e.printStackTrace();
}
}
executor.shutdown();
while (!executor.isTerminated()) {
}
System.out.println("Finished all threads");
int total=0;
for (int i=0; i< result.size(); i++) {
System.out.println("id = " + result.get(i)[0] + "; random number = "+ result.get(i)[1]);
total+=result.get(i)[1];
}
System.out.println("total = " + total);
}
/**
* @param args
*/
public static void main(String[] args)
{
Driver dr = new Driver();
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS");
cal = Calendar.getInstance();
System.out.println( "before " + sdf.format(cal.getTime()) );
//dr.doCalc(5);
dr.doCalcThread(5);
cal = Calendar.getInstance();
System.out.println( "after " + sdf.format(cal.getTime()) );
}
}
future.get();
是等待计算完成的阻塞操作。所以基本上你在你的循环中一次启动一个线程 - >没有任何并行性。这是错误的代码:
for (int i=0; i<n; i++) {
Work w = new Work(i);
Future<int[]> future =executor.submit(w);
int[] y;
try
{
y = future.get();
if (y != null) {
result.add(y);
}
} catch (InterruptedException | ExecutionException e)
{
e.printStackTrace();
}
}
所以基本上您需要将所有 Future<>
存储在列表中,并且在您提交所有这些之后开始调用它们的 get()
方法。这将允许任务 运行 并行。
就像 Svetlin Zarev 提到的,您的 future.get() 正在阻塞,但是如果您使用的是 java 8,我建议您查看 CompleteableFuture,因为您可以看到所有线程运行,并使用 CompleteableFuture.allOf() 检查它们是否全部完成,并在完成后添加结果