Java ThreadPool 限制创建的最大线程
Java ThreadPool limit maximum thread ever created
我正在尝试编写一个 Java 多线程程序,对作为文件给出的 2 个矩阵执行乘法运算,并使用 有限的线程总数 。
例如,如果我将线程数设置为 16,我希望我的线程池能够重用这 16 个线程,直到完成所有任务。
然而,对于更多的线程,我最终执行时间更长,而且我很难理解为什么。
可运行:
class Task implements Runnable
{
int _row = 0;
int _col = 0;
public Task(int row, int col)
{
_row = row;
_col = col;
}
@Override
public void run()
{
Application.multiply(_row, _col);
}
}
申请:
public class Application
{
private static Scanner sc = new Scanner(System.in);
private static int _A[][];
private static int _B[][];
private static int _C[][];
public static void main(final String [] args) throws InterruptedException
{
ExecutorService executor = Executors.newFixedThreadPool(16);
ThreadPoolExecutor pool = (ThreadPoolExecutor) executor;
_A = readMatrix();
_B = readMatrix();
_C = new int[_A.length][_B[0].length];
long startTime = System.currentTimeMillis();
for (int x = 0; x < _C.length; x++)
{
for (int y = 0; y < _C[0].length; y++)
{
executor.execute(new Task(x, y));
}
}
long endTime = System.currentTimeMillis();
executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.HOURS);
System.out.printf("Calculation Time: %d ms\n" , endTime - startTime);
}
public static void multMatrix(int row, int col)
{
int sum = 0;
for (int i = 0; i < _B.length; i++)
{
sum += _A[row][i] * _B[i][col];
}
_C[row][col] = sum;
}
...
}
矩阵计算和工作负载分担似乎是正确的,所以这可能是由于线程池使用不当造成的
使用提交而不是执行
列出返回的 Future
以便您可以等待它们。
List<Future<?>> futures = new ArrayList<>();
futures.add(executor.submit(new Task(x, y)));
然后等待这些期货完成。
这些线程已经被重新用于执行任务,这是 ThreadPoolExecutor 的预期行为。
http://www.codejava.net/java-core/concurrency/java-concurrency-understanding-thread-pool-and-executors
https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html
随着线程名称的增加,您将获得更长的计算时间,因为创建它们所需的时间大于并发性在执行相对短任务时提供的性能改进。
上下文切换需要时间。
如果你有 8 个核心并且你正在执行 8 个线程,它们都可以同时工作,并且一旦一个完成就会被重用。
另一方面,如果你有 8 个内核的 16 个线程,每个线程将竞争处理器时间,调度程序将切换这些线程,你的时间将增加到 - 执行时间 + 上下文切换。
线程越多,上下文切换越多,因此时间增加。
我正在尝试编写一个 Java 多线程程序,对作为文件给出的 2 个矩阵执行乘法运算,并使用 有限的线程总数 。
例如,如果我将线程数设置为 16,我希望我的线程池能够重用这 16 个线程,直到完成所有任务。
然而,对于更多的线程,我最终执行时间更长,而且我很难理解为什么。
可运行:
class Task implements Runnable
{
int _row = 0;
int _col = 0;
public Task(int row, int col)
{
_row = row;
_col = col;
}
@Override
public void run()
{
Application.multiply(_row, _col);
}
}
申请:
public class Application
{
private static Scanner sc = new Scanner(System.in);
private static int _A[][];
private static int _B[][];
private static int _C[][];
public static void main(final String [] args) throws InterruptedException
{
ExecutorService executor = Executors.newFixedThreadPool(16);
ThreadPoolExecutor pool = (ThreadPoolExecutor) executor;
_A = readMatrix();
_B = readMatrix();
_C = new int[_A.length][_B[0].length];
long startTime = System.currentTimeMillis();
for (int x = 0; x < _C.length; x++)
{
for (int y = 0; y < _C[0].length; y++)
{
executor.execute(new Task(x, y));
}
}
long endTime = System.currentTimeMillis();
executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.HOURS);
System.out.printf("Calculation Time: %d ms\n" , endTime - startTime);
}
public static void multMatrix(int row, int col)
{
int sum = 0;
for (int i = 0; i < _B.length; i++)
{
sum += _A[row][i] * _B[i][col];
}
_C[row][col] = sum;
}
...
}
矩阵计算和工作负载分担似乎是正确的,所以这可能是由于线程池使用不当造成的
使用提交而不是执行
列出返回的 Future
以便您可以等待它们。
List<Future<?>> futures = new ArrayList<>();
futures.add(executor.submit(new Task(x, y)));
然后等待这些期货完成。
这些线程已经被重新用于执行任务,这是 ThreadPoolExecutor 的预期行为。
http://www.codejava.net/java-core/concurrency/java-concurrency-understanding-thread-pool-and-executors https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ThreadPoolExecutor.html
随着线程名称的增加,您将获得更长的计算时间,因为创建它们所需的时间大于并发性在执行相对短任务时提供的性能改进。
上下文切换需要时间。 如果你有 8 个核心并且你正在执行 8 个线程,它们都可以同时工作,并且一旦一个完成就会被重用。 另一方面,如果你有 8 个内核的 16 个线程,每个线程将竞争处理器时间,调度程序将切换这些线程,你的时间将增加到 - 执行时间 + 上下文切换。
线程越多,上下文切换越多,因此时间增加。