Вот код, демонстрирующий использование интерфейса Callable <>:
public class test {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Callable callable = new Callable() {
@Override
public int[][] call() throws Exception {
int[][] array = new int[5][];
for (int i = 0; i < array.length; i++) {
array[i] = new int[]{5 * i, 5 * i + 1, 5 * i + 2, 5 * i + 3};
}
return array;
}
};
ExecutorService service = Executors.newFixedThreadPool(2);
Future<int[][]> result = service.submit(callable);
int[][] intArray = result.get();
for (int i = 0; i < intArray.length; i++) {
System.out.println(Arrays.toString(intArray[i]));
}
}
}
Для этого создается объект, который может быть передан в службу исполнителя. По сути, он такой же, как и Runnable, за исключением того, что он может возвращать значение; то, что мы делаем здесь, это создание ExecutorService с двумя потоками, а затем отправка этого вызываемого в службу.
Следующим, что происходит, является result.get (), который будет блокироваться до тех пор, пока не будет вызван вызываемый объект.
Вы, вероятно, не должны выполнять управление потоками самостоятельно.