Совместно используемые данные Java с Runnable против Callable и локальных данных
Первый случай. Допустим, у вас есть много задач, которые все возвращают какой-то результат, на данный момент давайте просто назовем его "результатом", и все они должны храниться в массиве. Есть два варианта:
1) Создайте один массив в основном методе и используйте runnables с доступом к общему списку и синхронизированным методом добавления
2) Создайте один массив в основном методе и используйте callable для выполнения задачи, верните результат и позвольте основному методу добавить Result в свой список.
Есть ли какие-то различия в производительности между ними, поскольку для запуска требуется синхронный доступ, а для вызовов - нет?
Затем, во втором случае: давайте теперь скажем, что каждая задача генерирует "маленький" массив, скажем, менее 10 элементов на задачу. Это снова дает два варианта:
1) Один массив в main и runnables с доступом к общему списку, который добавляет элементы результата при генерировании.
2) Один arrayList в main и вызываемых> с каждым собственным локальным массивом, который хранит результаты до тех пор, пока задача не будет завершена, а затем в main addAll используется для добавления найденного результата.
Тот же вопрос, что и раньше, в чем разница в производительности?
Для ясности, производительность как с точки зрения скорости (некоторые проблемы с синхронизацией и т. Д.), Так и с точки зрения памяти (используют ли вызываемые объекты гораздо больше памяти из-за локального небольшого массива или это мало, чтобы пренебречь)?
1 ответ
For the First Case:
Вариант первый: если мы используем задачи Runnable, то мы не можем получить что-либо возвращаемое из метода run(). Поэтому я думаю, что этот вариант не будет соответствовать вашим требованиям.
Вариант второй: Callable Согласно моему пониманию вашего требования, Callable является хорошим кандидатом. Но есть небольшое изменение: мы создадим список Future и для каждой задачи Callable(которую мы представим исполнителям) добавим в этот список результат Future этого Callable(подробности см. Ниже). Тогда всякий раз, когда нам нужен результат какой-либо задачи, мы можем получить результат из соответствующего будущего.
class MainTaskExecutor {
private static ExecutorService exe = Executors.newCachedThreadPool();
private static List<Future<Result>> futureResults = new ArrayList<>();
public static void main(String[] args) throws ExecutionException, InterruptedException {
Callable<Result> dummyTask = ()-> {
System.out.println("Task is executed");
Result dummyResult = new Result();
return dummyResult;
};
//Submit a task
submitTask(dummyTask);
//Getting result of "0" index
System.out.println(futureResults.get(0).get());
}
private static void submitTask(Callable<Result> task) {
futureResults.add(exe.submit(task));
}
private static Result getResult(int taskNumber) throws ExecutionException, InterruptedException {
return futureResults.get(taskNumber).get();
}
}
class Result {
// data to be added
}