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

Я реализую подключения к базе данных для своей мобильной игры.

Я создал пул соединений (он точно работает) и пул потоков, как показано ниже:

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() методов в запросы для выполнения BlockingQueue. ThreadPool должен истощать 3 executeQuery() в каждом потоке и выполнять методы параллельно.

Что происходит?

Я всегда получаю вывод в таком порядке (конечно, больший вывод):

query 1
query 2
query 3
query 1
query 2
query 3

что означает, что задачи не запускаются параллельно. Если бы они запускались параллельно, я бы получил «случайный» порядок System.out, верно?

Я делаю что-то неправильно? Мой процессор Intel Core i5 с 4 рабочими потоками. Я использую ThreadPool в первый раз.

Спасибо за любые идеи!


person Community    schedule 11.10.2016    source источник
comment
У вас есть только одна задача в вашем пуле потоков?   -  person tkausl    schedule 11.10.2016
comment
Я вызываю scheduleTaskExecutor.scheduleAtFixedRate только один раз в начале приложения. Это неправильно? Я думал, что он должен просто запустить 5 потоков, и каждый из этих потоков будет вызывать queryDatabase(); каждые 300 мс.   -  person    schedule 11.10.2016
comment
Нет, пул потоков не выполняет одну задачу в нескольких потоках. У вас может быть много задач в одном пуле, и пул будет запускать 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.   -  person tkausl    schedule 11.10.2016
comment
Я читал, но почему-то не увидел эту часть. О мой Бог. Спасибо. Вы знаете, как вызвать queryDatabase() параллельно с помощью 5 разных потоков?   -  person    schedule 11.10.2016
comment
@Spectre создает 5 разных экземпляров Runnable с вызовами queryDatabase() и отправляет их все в пул потоков.   -  person Alexei Kaigorodov    schedule 12.10.2016


Ответы (1)


Вы планируете только одну задачу в планировщике. Так что эта задача всегда выполняется последовательно. Вы можете попробовать запланировать одну и ту же задачу несколько раз.

Параметр newScheduledThreadPool указывает только, сколько потоков нужно поддерживать, даже если ничего не нужно выполнять. Это более или менее параметр настройки производительности.

person Florian Albrecht    schedule 11.10.2016
comment
Зачем тогда использовать newScheduledThreadPool? :D Хорошо. Теперь я все понимаю. Но что я должен использовать для параллельных вызовов queryDatabase() 5 разными потоками? - person ; 11.10.2016
comment
Просто скопируйте и вставьте строку scheduleAtFixedRate или поместите ее в цикл for. - person Florian Albrecht; 11.10.2016