У меня есть сеть потоков Java (потоковое программирование), обменивающихся данными по каналам с фиксированной пропускной способностью - работающих под управлением WindowsXP. На основании нашего опыта работы с «зелеными» потоками (без вытеснения) мы ожидали, что потоки будут реже переключать контекст (таким образом сокращая время ЦП), если каналы станут больше. Однако мы обнаружили, что увеличение размера канала не влияет на время выполнения. Кажется, что происходит то, что Java решает переключать потоки, даже если каналы не заполнены или пусты (то есть, хотя поток не должен приостанавливаться), что тратит время процессора без видимых преимуществ. Также изменение приоритетов потоков не имеет заметной разницы.
Мой вопрос заключается в том, существует ли какой-то способ убедить Java не делать ненужных переключений контекста, а отложить переключение до тех пор, пока действительно не будет необходимости переключать потоки - есть ли способ изменить логику диспетчеризации Java? Или это реагирует на то, на что я не обращал внимания ?! Или есть другие механизмы асинхронизма, например, Фабрики потоков, Runnable (s), возможно, даже демоны (!). Ответ кажется неочевидным, так как до сих пор ни один из моих корреспондентов не придумал ответ (включая совсем недавно двух профессоров CS). Или, может быть, я упускаю что-то настолько очевидное, что люди не могут представить, что я этого не знаю ...
Я добавил сюда код отправки и получения - не очень элегантно, но, похоже, он работает ... ;-) Если вам интересно, я подумал, что логика goLock в 'send' может вызывать проблему, но удаление его временно не имело никакого значения. Я добавил код для отправки и получения ...
</p>
<p>public synchronized Packet receive() {</p>
<pre><code>if (isDrained()) {
return null;
}
while (isEmpty()) {
try {
wait();
} catch (InterruptedException e) {
close();
return null;
}
if (isDrained()) {
return null;
}
}
if (isDrained()) {
return null;
}
if (isFull()) {
notifyAll(); // notify other components waiting to send
}
Packet packet = array[receivePtr];
array[receivePtr] = null;
receivePtr = (receivePtr + 1) % array.length;
//notifyAll(); // only needed if it was full
usedSlots--;
packet.setOwner(receiver);
if (null == packet.getContent()) {
traceFuncs("Received null packet");
} else {
traceFuncs("Received: " + packet.toString());
}
return packet;
}
синхронизированная логическая отправка (окончательный пакетный пакет, конечная операция OutputPort) {
sender = op.sender;
if (isClosed()) {
return false;
}
while (isFull()) {
try {
wait();
} catch (InterruptedException e) {
indicateOneSenderClosed();
return false;
}
sender = op.sender;
}
if (isClosed()) {
return false;
}
try {
receiver.goLock.lockInterruptibly();
} catch (InterruptedException ex) {
return false;
}
try {
packet.clearOwner();
array[sendPtr] = packet;
sendPtr = (sendPtr + 1) % array.length;
usedSlots++; // move this to here
if (receiver.getStatus() == StatusValues.DORMANT || receiver.getStatus() == StatusValues.NOT_STARTED) {
receiver.activate(); // start or wake up if necessary
} else {
notifyAll(); // notify receiver
// other components waiting to send to this connection may also get
// notified,
// but this is handled by while statement
}
sender = null;
Component.network.active = true;
} finally {
receiver.goLock.unlock();
}
return true;
}
спасибо за вопрос! Я обсуждаю тот же вопрос на форуме Sun, и вот мой последний пост на этом форуме:
Наше лучшее предположение сейчас состоит в том, что этот эффект является результатом Windows '
логика планирования.
Microsoft, похоже, признает, что эта область нуждается в некотором улучшении
как он представляет UMS - цитирую: «UMS рекомендуется для приложений
с высокими требованиями к производительности, которые должны эффективно выполнять многие
потоки одновременно в многопроцессорных или многоядерных системах. ... UMS это
доступно начиная с 64-битных версий Windows 7 и Windows
Сервер 2008 R2. Эта функция недоступна в 32-разрядных версиях
Windows. «Будем надеяться, что в будущем Java будет использовать UMS.
релиз.
Спасибо за вашу помощь!