我有一个通过固定容量通道进行通信的 Java 线程网络(基于流的编程) - 在 WindowsXP 下运行。根据我们对“绿色”线程(非抢占式)的经验,我们期望的是,如果通道更大,线程切换上下文的频率会降低(从而减少 CPU 时间)。但是,我们发现增加通道大小对运行时间没有任何影响。似乎正在发生的事情是,即使通道未满或未空(即即使线程不必挂起),Java 仍决定切换线程,这会花费 CPU 时间而没有明显优势。更改线程优先级也不会产生任何明显的差异。
我的问题是是否有某种方法可以说服 Java 不要进行不必要的上下文切换,而是推迟切换,直到确实需要切换线程 - 是否有某种方法可以改变 Java 的调度逻辑?还是它对我没有注意的事情做出反应?!或者是否有其他异步机制,例如线程工厂、Runnable(s),甚至可能是守护进程(!)。答案似乎并不明显,因为到目前为止,我的通讯员都没有提出答案(包括最近的两位 CS 教授)。或者,也许我错过了一些如此明显以至于人们无法想象我不知道的东西......
我在这里添加了发送和接收代码 - 不是很优雅,但它似乎工作......;-) 如果您想知道,我认为“发送”中的 goLock 逻辑可能会导致问题,但将其删除暂时没有任何区别。我已经添加了发送和接收的代码......
public synchronized Packet receive() {
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;
}
synchronized boolean send(final Packet packet, final OutputPort op) {
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 的调度逻辑造成的。
微软似乎承认这个领域需要一些改进,因为它正在引入 UMS - 我引用:“UMS 推荐用于需要在多处理器或多核系统上同时有效运行多个线程的高性能要求的应用程序。...... UMS 可用从 64 位版本的 Windows 7 和 Windows Server 2008 R2 开始。此功能在 32 位版本的 Windows 上不可用。希望 Java 将在以后的某个版本中利用 UMS。
谢谢你的帮助!