【问题标题】:Thread's run does not see its array size increase线程的运行没有看到它的数组大小增加
【发布时间】:2012-11-06 22:00:22
【问题描述】:

我目前正在做 Java 作业。我被要求创建一个基本的 DNS 服务器。 有一个 UDPSender 类,它是一个侦听端口 53 的线程。 还有另一个线程叫做 UDPManager。

UDPManager 使用一个嵌套的可运行类启动一个线程,该类包含一个 DatagramPacket 的 ArrayList。 UDPSender 聚合 UDPManager,每当它收到一个 UDP 数据包时,它就会将它发送给 manager 让他将它添加到 arrayList。

import java.net.DatagramPacket;
import java.util.ArrayList;
import java.util.HashMap;


public class UDPManager {
private UDPManagerRunnable manager;

public UDPManager(String hostsFile, String remoteDNS, boolean localResolution) {
    manager = new UDPManagerRunnable(hostsFile, remoteDNS, localResolution);
    new Thread(manager).start();
}

public void managePacket(DatagramPacket p) {
    manager.managePacket(p);
}

public void close() {
    manager.close();
}

private class UDPManagerRunnable implements Runnable {
    private ArrayList<DatagramPacket> packets;
    private HashMap<Integer, String> clients;
    private boolean localResolution;
    private boolean running;
    private String hostsFile;
    private String remoteDNS;

    public UDPManagerRunnable(String hostsFile, String remoteDNS, boolean localResolution) {
        packets = new ArrayList<DatagramPacket>();
        clients = new HashMap<Integer, String>();
        this.localResolution = localResolution;
        this.running = true;
        this.hostsFile = hostsFile;
        this.remoteDNS = remoteDNS;
    }

    public void managePacket(DatagramPacket p) {
        packets.add(p);
        System.out.println("Received packet. "+packets.size());
    }

    public void close() {
        running = false;
    }

    public void run() {
        DatagramPacket currentPacket = null;
        while(running) {
            if(!packets.isEmpty()) {
                currentPacket = packets.remove(0);
                byte[] data = currentPacket.getData();
                int anCountValue = data[Constant.ANCOUNT_BYTE_INDEX];
                if(anCountValue == Constant.ANCOUNT_REQUEST)
                    this.processRequest(currentPacket);
                else if(anCountValue == Constant.ANCOUNT_ONE_ANSWER)
                    this.processResponse(currentPacket);

            }
        }

    }

    private void processRequest(DatagramPacket packet) {
        System.out.println("it's a request!");
    }

    private void processResponse(DatagramPacket packet) {
        System.out.println("it's a response!");
    }

}

}

这是 UDPManager。当 System.out.println 正确显示“已接收数据包”时,数据包会正确传输到管理器。并且数组的大小确实增加了。我遇到的问题是在“run()”内部它永远不会看到大小增加。奇怪的是它在调试中工作得非常好。 知道它为什么会这样吗?

非常感谢您的帮助。

【问题讨论】:

  • 应该增加哪个数组,在哪里增加?
  • "packets",在 UDPManagerRunnable 中。在 managePacket 方法中添加元素。
  • 好吧,首先你不要在任何地方调用该方法。
  • 这是一个经典的生产者消费者问题。你应该使用BlockingQueue
  • 很抱歉,这是我第一次在论坛上寻求帮助。我想我还不是很清楚。 UDPManager 上有另一个线程调用该方法,它工作正常。问题只是在运行内部,由于某种原因,它似乎没有查看同一个数组,因为它总是将数组视为空。

标签: java multithreading arraylist


【解决方案1】:

你应该在访问或修改它时同步数据包

【讨论】:

    【解决方案2】:

    问题是,您的第一个线程将新数据放入 packets 变量中,但对于第二个线程,这是不可见的。您应该同步对数组的访问。

    当您启动第二个线程时,所有变量都会被复制。第二个线程只处理副本。您需要同步访问此变量,以便其他线程可以看到更改。

    【讨论】:

    • -1 这不是问题。如果列表引用被更改,那将是一个问题,但事实并非如此。副本仅由引用而不是整个对象组成,并且引用永远不会改变 - 只有一个 List 对象。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-15
    • 1970-01-01
    相关资源
    最近更新 更多