1. Overview
1.概述
In this tutorial, we’ll run through different options available for passing parameters to a Java thread.
在本教程中,我们将介绍向Java 线程传递参数的不同选项。
2. Thread Fundamentals
2.线程基础
As a quick reminder, we can create a thread in Java by implementing Runnable or Callable.
作为快速提醒,我们可以通过实现Runnable 或Callable在Java中创建一个线程。
To run a thread, we can invoke Thread#start (by passing an instance of Runnable) or use a thread pool by submitting it to an ExecutorService.
要运行一个线程,我们可以调用Thread#start(通过传递一个Runnable的实例)或者使用一个线程池,将其提交给ExecutorService。
Neither of these approaches accepts any extra parameters, though.
不过,这两种方法都不接受任何额外的参数。
Let’s see what can we do to pass parameters to a thread.
让我们看看我们能做些什么来向线程传递参数。
3. Sending Parameters in the Constructor
3.在构造函数中发送参数
The first way we can send a parameter to a thread is simply providing it to our Runnable or Callable in their constructor.
我们向线程发送参数的第一种方式是简单地将其提供给我们的Runnable或Callable的构造函数。
Let’s create an AverageCalculator that accepts an array of numbers and returns their average:
让我们创建一个AverageCalculator,它接受一个数字数组并返回其平均值。
public class AverageCalculator implements Callable<Double> {
int[] numbers;
public AverageCalculator(int... numbers) {
this.numbers = numbers == null ? new int[0] : numbers;
}
@Override
public Double call() throws Exception {
return IntStream.of(numbers).average().orElse(0d);
}
}
Next, we’ll provide some numbers to our average calculator thread and validate the output:
接下来,我们将为我们的平均计算器线程提供一些数字,并验证输出。
@Test
public void whenSendingParameterToCallable_thenSuccessful() throws Exception {
ExecutorService executorService = Executors.newSingleThreadExecutor();
Future<Double> result = executorService.submit(new AverageCalculator(1, 2, 3));
try {
assertEquals(2.0, result.get().doubleValue());
} finally {
executorService.shutdown();
}
}
Note that the reason this works is that we’ve handed our class its state before launching the thread.
请注意,这样做的原因是,我们在启动线程之前已经将其状态交给了我们的类。
4. Sending Parameters Through a Closure
4.通过闭包发送参数
Another way of passing parameters to a thread is by creating a closure.
另一种向线程传递参数的方式是通过创建一个闭包.。
A closure is a scope that can inherit some of its parent’s scope – we see it with lambdas and anonymous inner classes.
外壳是一个可以继承其父级范围的作用域–我们在lambdas和匿名内类中看到它。
Let’s extend our previous example and create two threads.
让我们扩展之前的例子,创建两个线程。
The first one will calculate the average:
第一个将计算出平均数。
executorService.submit(() -> IntStream.of(numbers).average().orElse(0d));
And, the second will do the sum:
而且,第二个人将做和。
executorService.submit(() -> IntStream.of(numbers).sum());
Let’s see how we can pass the same parameter to both threads and get the result:
让我们看看如何将相同的参数传递给两个线程并获得结果。
@Test
public void whenParametersToThreadWithLamda_thenParametersPassedCorrectly()
throws Exception {
ExecutorService executorService = Executors.newFixedThreadPool(2);
int[] numbers = new int[] { 4, 5, 6 };
try {
Future<Integer> sumResult =
executorService.submit(() -> IntStream.of(numbers).sum());
Future<Double> averageResult =
executorService.submit(() -> IntStream.of(numbers).average().orElse(0d));
assertEquals(Integer.valueOf(15), sumResult.get());
assertEquals(Double.valueOf(5.0), averageResult.get());
} finally {
executorService.shutdown();
}
}
One important thing to remember is to keep the parameters effectively final or we won’t be able to hand them to the closure.
要记住的一件事是,有效地保持参数的终结性,否则我们将无法将它们交给闭包。
Also, the same concurrency rules apply here as everywhere. If we change a value in the numbers array while the threads are running, there is no guarantee that they will see it without introducing some synchronization.
此外,这里适用的并发规则与其他地方相同。如果我们在线程运行时改变了numbers数组中的一个值,在没有引入一些同步的情况下,无法保证它们会看到这个值。
And to wrap up here, an anonymous inner class would have worked, too, say if we are using an older version of Java:
在此总结一下,如果我们使用的是旧版本的Java,一个匿名的内层类也会起作用。
final int[] numbers = { 1, 2, 3 };
Thread parameterizedThread = new Thread(new Callable<Double>() {
@Override
public Double call() {
return calculateTheAverage(numbers);
}
});
parameterizedThread.start();
5. Conclusion
5.结论
In this article, we discovered the different options available for passing parameters to a Java thread.
在这篇文章中,我们发现了向Java线程传递参数的不同选项。
As always, the code samples are available over on Github.
像往常一样,代码样本可在Github上获得。