有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java同步在TimerTask中失败

我正在开发一个ODL应用程序,并从我的主要功能中安排了一个任务(MonitorLinksTask),以便监控拓扑结构的所有链接中的延迟我想在每条链路上发送一个数据包,在控制器接收到数据包后,为下一条链路发送下一个数据包中的代码是:

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

有什么想法吗


共 (1) 个答案

  1. # 1 楼答案

    假设所有这些都发生在同一个JVM中:

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

    由于以上帮助解决了您的问题,很明显,这是由于线程(TimerTask线程和您的应用程序线程)之间缺乏可见性更新造成的。让我建议Oracle Concurrency进一步了解Java多线程。您的具体问题已提到here