Почему мой пул потоков не работает параллельно в Java?

#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 .