同步在计时器任务中失败



我正在开发一个 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 中:

  1. Thread.currentThread().getName()添加到日志中,以便从日志中清除执行是多线程还是单线程;
  2. 如果是前者,请尝试将volatile修饰符添加到flag

由于上述内容有助于解决您的问题,因此很明显,这是由于线程(TimerTask线程和应用线程)之间缺乏可见性更新引起的。让我推荐 Oracle 并发,以进一步了解 Java 多线程。此处提到了您的具体问题。

相关内容

最新更新