我正在开发ODL应用程序,并已从我的主要功能中安排了一个任务(MonitorLinksTask
),以便监视拓扑的所有链接中的延迟。我想为每个链接发送一个数据包,并且在控制器接收到它之后,为下一个链接发送下一个数据包。 main
中的代码是:
Timer time = new Timer();
MonitorLinksTask monitorLinksTask = new MonitorLinksTask();
time.schedule(monitorLinksTask, 0, 5000);
类
MonitorLinksTask
是:public class MonitorLinksTask extends TimerTask{
static boolean flag = false;
public void run() {
for (DomainLink link : linkList) {
sendPacket();
while (flag == false){
//waits until it gets notified that the sent packet has been received
}
System.out.println("Sending next packet.");
System.out.println("----------");
flag = false;
}
}
}
哪里:
private void sendPacket(){
Packet packet;
PacketProcessingService packetProcessingService = ... ;
// .... fill the packet ....
System.out.println("Packet transmitted at time " + System.currentTimeMillis());
packetProcessingService.transmitPacket(packet);
}
到目前为止,任务每5秒钟运行一次,并调用该函数为每个链接发送一个数据包,以计算图中每个链接的单程延迟。
我创建了一个监听器,以便每次控制器接收到一个数据包时,它都会通知
MonitorLinksTask
它已接收到该数据包,然后MonitorLinksTask
可以发送下一个数据包。public void onPacketReceived(PacketReceived packetReceived) {
System.out.println("Packet received at time " + System.currentTimeMillis());
MonitorLinksTask.flag = true;
}
但是,我的程序对于
MonitorLinksTask
的前两个执行是正确的,而第三个执行则停止了。具有两个链接的案例的示例输出:Packet transmitted at time 1549333576093
Packet received at time 1549333576096
Sending next packet.
Packet transmitted at time 1549333576111
Packet received at time 1549333576115
Sending next packet.
----------
Packet transmitted at time 1549333576122
Packet received at time 1549333576124
Sending next packet.
Packet transmitted at time 1549333576128
Packet received at time 1549333576129
Sending next packet.
----------
Packet transmitted at time 1549333576136
Packet received at time 1549333576140
有任何想法吗?
最佳答案
假设所有这些都发生在同一个JVM中:
将Thread.currentThread().getName()
添加到日志中,以便在执行是多线程还是单线程时从日志中清除;
如果以前是,请尝试在volatile
中添加flag
修饰符。
由于上述内容有助于解决您的问题,因此很显然,这是由于线程(TimerTask
线程和您的应用程序线程)之间缺少可见性更新引起的。让我建议Oracle Concurrency以进一步了解Java多线程。您提到的特定问题是here。