#java #multithreading #callable
#java #многопоточность #вызываемый
Вопрос:
Я хочу контролировать количество времени, которое использует каждый поток.
Один поток выполняет некоторую обработку, а другой обрабатывает данные в базе данных, но вставка происходит медленнее, чем обработка, из-за объема сгенерированных данных. Я хочу выделить больше процессорного времени для вставки этих данных.
Возможно ли это сделать с потоками? На данный момент я переводлю поток, выполняющий обработку, в режим ожидания, но время вставки меняется в зависимости от машины. Есть ли другой способ, которым я могу это сделать? Является ли способ, включающий использование синхронизации потоков внутри моей программы?
Ответ №1:
Вы можете увеличить приоритет потока, используя Thread.setPriority(…), но это не идеально.
Возможно, вы можете использовать некоторую форму блокирующей очереди из пакета java.util.concurrent, чтобы заставить один поток ждать, пока другой поток что-то делает. Например, SynchronousQueue можно использовать для отправки сообщения из одного потока в другой поток о том, что он теперь может что-то сделать.
Другой подход заключается в использовании исполняемых файлов вместо потоков и отправке исполняемых файлов исполнителю, такому как ThreadPoolExecutor. Этот исполнитель будет следить за тем, чтобы исполняемые файлы использовали достаточное количество времени.
Ответ №2:
Первое, что следует упомянуть, это то, что приоритет потока сам по себе не означает «доля процессора». Похоже, существует много путаницы в отношении того, что на самом деле означает приоритет потока, отчасти потому, что это на самом деле означает разные вещи в разных ОС. Если вы работаете в Linux, это на самом деле означает что-то близкое к относительной доле процессора. Но под Windows это определенно не так. Поэтому, если это может помочь, вы можете сначала взглянуть на некоторую информацию, которую я собрал некоторое время назад о приоритетах потоков в Java, которая объясняет, что на самом деле означают приоритеты потоков в разных системах.
Общий ответ на ваш вопрос заключается в том, что если вы хотите, чтобы поток занимал определенную долю ЦП, лучше неявно делать это программно: периодически, для каждого «фрагмента» обработки, измеряйте, сколько времени прошло (или сколько было использовано ЦП — строго говоря, они не одинаковывещь), затем отложите соответствующее количество времени, чтобы соотношение обработки / ожидания составило примерно% от предполагаемого времени обработки.
Однако я не уверен, что это действительно поможет вашей задаче здесь.
Как я понимаю, в основном у вас есть задача вставки, которая является шагом, определяющим скорость. При обычных обстоятельствах маловероятно, что система «намеренно выделяет меньше ЦП, чем может или должно» потоку, выполняющему эту вставку.
Так что, вероятно, больше времени потребуется, чтобы посмотреть на эту задачу вставки и посмотреть, можно ли программно изменить способ выполнения этой задачи вставки. функции. Например: можете ли вы вставлять большими партиями? если процесс вставки действительно по какой-то причине привязан к процессору (что я подозреваю), можете ли вы сделать его многопоточным? почему ваше приложение на самом деле заботится о том, чтобы дождаться завершения вставки, и можете ли вы изменить эту зависимость?
Если вставка выполняется в стандартную систему БД, интересно, сильно ли эта вставка связана с процессором?
Ответ №3:
Одним из способов было бы установить приоритет потока обработки ниже, чем у другого. Но будьте осторожны, это не рекомендуется, поскольку это не позволит сохранить независимость вашего кода от платформы. (Разные приоритеты потоков ведут себя по-разному на разных платформах).
Другим способом было бы использовать службу, в которой поток базы данных продолжал бы отправлять сообщения о своем текущем состоянии (возможно, какой-то флаг «aboutToOver»).
Или используйте синхронизацию, скажем, двоичный семафор. Когда поток базы данных работает, другой поток будет заблокирован, и, следовательно, поток БД будет использовать все ресурсы. Но опять же поток обработки будет заблокирован в то же время. На самом деле это будет лучшим решением, поскольку поток processign может выполнять, скажем, 3-4 задачи, а затем будет заблокирован семафором до тех пор, пока позже он снова не сможет встать и выполнить задачу