#java #multithreading #parallel-processing #threadpoolexecutor
#java #многопоточность #параллельная обработка #threadpoolexecutor
Вопрос:
Я внедряю подключения к базе данных для своей мобильной игры.
Я создал пул соединений (он работает наверняка) и пул потоков, как показано ниже:
private ScheduledExecutorService scheduleTaskExecutor = Executors.newScheduledThreadPool(5);
Я запускаю задачи только один раз, как это в начале:
scheduleTaskExecutor.scheduleAtFixedRate(new Runnable() {
public void run() {
queryDatabase();
}
}, 0, 300, TimeUnit.MILLISECONDS);
Мой queryDatabase()
метод выглядит так:
private void queryDatabase(){
List<DataBaseQuery> queriesToExecute = new LinkedList<>();
if(queries.drainTo(queriesToExecute, 3) == 0){
queriesToExecute.add(queries.take());
}
for(DataBaseQuery query: queriesToExecute) {
query.executeQuery();
}
}
executeQuery()
это метод интерфейса, который я реализую в коде, и он выглядит так:
@Override
public void executeQuery(){
// get connection from the pool
System.out.println("query 1");
doFirstQuery(); // do first query (20-100ms) for ex. check if user already exists. Function will block for 20-100ms
System.out.println("query 2");
// do second query (20-100ms) for ex. check if email exists
System.out.println("query 3");
// do third query (20-100ms) for ex. insert new user
}
Мой тестовый пример:
Я ввел 100 одинаковых executeQuery()
методов в queriesToExecute BlockingQueue . Пул потоков должен выполнять 3 ExecuteQuery() в каждом потоке и выполнять методы параллельно.
Что происходит?
Я всегда получаю вывод в этом порядке (больший вывод, конечно):
query 1
query 2
query 3
query 1
query 2
query 3
это означает, что задачи не запускаются параллельно. Если бы они выполнялись параллельно, я бы получил «случайный» порядок System.out, верно?
Я делаю что-то не так? Мой процессор Intel Core i5 с 4 рабочими потоками. Я использую пул потоков впервые.
Спасибо за любые идеи!
Комментарии:
1. У вас есть только одна задача в вашем пуле потоков?
2. Я вызываю
scheduleTaskExecutor.scheduleAtFixedRate
только один раз в начале приложения. Это неправильно? Я думал, что он должен просто запускать 5 потоков, и каждый из этих потоков будет вызывать queryDatabase(); каждые 300 мс.3.Нет, пул потоков не выполняет одну задачу в нескольких потоках. У вас может быть много задач в одном пуле, и пул будет запускать X из них одновременно, где X — количество потоков, однако одна задача никогда не будет выполняться одновременно. См . scheduleAtFixedRate
If any execution of this task takes longer than its period, then subsequent executions may start late, but will not concurrently execute.
4. Я прочитал это, но почему-то не увидел эту часть. Боже мой. Спасибо. Есть ли у вас какие-либо подсказки, как вызывать
queryDatabase()
параллельно 5 разными потоками?5. @Spectre создайте 5 разных экземпляров Runnable с вызовами queryDatabase() и отправьте их все в пул потоков.
Ответ №1:
Вы планируете только одну задачу в своем планировщике. Таким образом, эта задача всегда выполняется последовательно. Вы можете попробовать планировать одну и ту же задачу несколько раз.
newScheduledThreadPool
Параметр указывает только, сколько потоков поддерживать в рабочем состоянии, даже если ничего не должно выполняться. Это более или менее параметр настройки производительности.
Комментарии:
1. Зачем тогда использовать newScheduledThreadPool? : D Ок. Теперь я все понял. Но что я должен использовать для выполнения параллельных вызовов с
queryDatabase()
помощью 5 разных потоков?2. Просто скопируйте и вставьте строку scheduleAtFixedRate или поместите ее в цикл for .