Строки сами по себе неизменяемы, но вы можете легко создать обратную копию со следующим кодом:
function reverseString(str) {
var strArray = str.split("");
strArray.reverse();
var strReverse = strArray.join("");
return strReverse;
}
reverseString("hello");
Действительно ли это дорого для создания нового потока?
В качестве эталона я создал 60 000 потоков с Runnable
s с пустым run()
методами. После создания каждого потока я немедленно вызвал его метод start(..)
. Это заняло около 30 секунд интенсивной работы процессора. Аналогичные эксперименты были выполнены в ответ на этот вопрос . Резюме состоит в том, что если потоки не заканчиваются сразу, а большое количество активных потоков накапливается (несколько тысяч), тогда будут проблемы: (1) каждый поток имеет стек, поэтому у вас закончится нехватка памяти , (2) может быть ограничение на количество потоков на процесс, налагаемый ОС, но не обязательно, кажется .
Итак, насколько я могу видеть , если мы говорим о запуске сказать 10 потоков в секунду, и все они заканчиваются быстрее, чем новые, и мы можем гарантировать, что этот показатель не будет превышен слишком сильно, тогда ExecutorService не предлагает каких-либо конкретных преимуществ в видимой производительности или стабильности. (Хотя он все же может сделать его более удобным или читаемым, чтобы выразить определенные идеи параллелизма в коде.) С другой стороны, если вы можете планировать сотни или тысячи задач в секунду, что требует времени для запуска, вы можете столкнуться с большими проблемами сразу. Это может произойти неожиданно, например. если вы создаете потоки в ответ на запросы на сервер, и есть интенсивность запросов, которые получает ваш сервер. Но, например, один поток в ответ на каждое событие ввода пользователя (нажатие клавиши, движение мыши) кажется совершенно прекрасным, если задачи кратки.
Создание большого количества потоков без ограничения максимального порога может привести к тому, что приложение выйдет из памяти кучи. Из-за этого создание ThreadPool намного лучше. Используя ThreadPool, мы можем ограничить количество потоков, которые можно объединить и повторно использовать.
Структура исполнителей облегчает процесс создания пулов потоков в java. Класс исполнителей обеспечивает простую реализацию ExecutorService с использованием ThreadPoolExecutor.
Источник:
До версии java 1.5 Thread / Runnable был разработан для двух отдельных сервисов
ExecutorService отделяет эти две службы, обозначая Runnable / Callable как единицу работы и Исполнитель в качестве механизма для выполнения (с использованием жизненного цикла) единицы работы
ExecutorService также предоставляет доступ к FutureTask, который вернет вызывающему классу результаты фоновой задачи после завершения. В случае реализации Callable
public class TaskOne implements Callable<String> {
@Override
public String call() throws Exception {
String message = "Task One here. . .";
return message;
}
}
public class TaskTwo implements Callable<String> {
@Override
public String call() throws Exception {
String message = "Task Two here . . . ";
return message;
}
}
// from the calling class
ExecutorService service = Executors.newFixedThreadPool(2);
// set of Callable types
Set<Callable<String>>callables = new HashSet<Callable<String>>();
// add tasks to Set
callables.add(new TaskOne());
callables.add(new TaskTwo());
// list of Future<String> types stores the result of invokeAll()
List<Future<String>>futures = service.invokeAll(callables);
// iterate through the list and print results from get();
for(Future<String>future : futures) {
System.out.println(future.get());
}
Преимущество, которое я вижу, заключается в управлении / планировании нескольких потоков. С помощью ExecutorService вам не нужно писать свой собственный менеджер потоков, который может быть запутан с ошибками. Это особенно полезно, если ваша программа должна запускать сразу несколько потоков. Например, вы хотите выполнить два потока за раз, вы можете легко сделать это следующим образом:
ExecutorService exec = Executors.newFixedThreadPool(2);
exec.execute(new Runnable() {
public void run() {
System.out.println("Hello world");
}
});
exec.shutdown();
Пример может быть тривиальным, но попытайтесь считать, что строка «hello world» состоит из и вы хотите, чтобы эта операция выполнялась в нескольких потоках за раз, чтобы улучшить производительность вашей программы. Это всего лишь один пример. Есть еще много случаев, когда вы планируете или запускаете несколько потоков и используете ExecutorService в качестве менеджера потоков.
Для запуска одного потока я не вижу явного преимущества используя ExecutorService.
Thread
, когда все, что вам нужно, это Runnable
... вы даже не запускаете Thread
, поэтому он только добавляет путаницу и ненужный багаж.
– ColinD
21 October 2010 в 05:00
exec.shutdown();
в заявлении finally с нулевой проверкой.
– Aniket Thakur
28 January 2017 в 21:33
Ниже приведены некоторые преимущества:
Следующие ограничения от традиционной Thread, преодолеваемые инфраструктурой Executor (встроенная структура пула потоков).
StackOverflowException
, поэтому наша JVM сработает. Преимущества пула потоков