Java多线程I / 0和通信问题

我正在使用Java创建用于网络管理的应用程序。在此应用程序中,我使用SNMP4j库(用于snmp协议)建立与网络设备的通信。因此,我应该使用此协议扫描网络设备的某些值,并将结果放入文件中进行缓存。最后,我决定使我的应用程序成为多线程,并为线程分配设备。我创建了一个实现可运行接口的类,然后扫描每个设备所需的值。 当我独自上课时,它可以正常工作。但是当我同时放置多个线程时,输出混乱了,它会将其他输出或乱序输出打印到文件中。现在,我想知道这个问题是由于I / O还是由于通信。 在这里,我将放置一些代码,以便您可以看到正在执行的操作并帮助我确定出现了什么问题。
public class DeviceScanner implements Runnable{
private final SNMPCommunicator comm;
private OutputStreamWriter out;

public DeviceScanner(String ip, OutputStream output) throws IOException {
        this.device=ip;
        this.comm = new SNMPV1Communicator(device);

        oids=MIB2.ifTableHeaders;
        out = new OutputStreamWriter(output);

    }

@Override
    public void run(){
//Here I use the communicator to request for desired data goes something like ...
                String read=\"\"
        for (int j=0; j<num; j++){

                read= comm.snmpGetNext(oids);
                out.write(read);
                this.updateHeaders(read);

            }
            out.flush();
//...
   }

}
一些预期的输出将是这样的: 1.3.6.1.2.1.1.1.0 = SmartSTACK ELS100-S24TX2M 1.3.6.1.2.1.1.2.0 = 1.3.6.1.4.1.52.3.9.1.10.7 1.3.6.1.2.1.1.3.0 = 26天,22:35:02.31 1.3.6.1.2.1.1.4.0 =管理员 1.3.6.1.2.1.1.5.0 = els 1.3.6.1.2.1.1.6.0 =机房 但是相反,我得到的东西像(变量): 1.3.6.1.2.1.1.1.0 = SmartSTACK ELS100-S24TX2M 1.3.6.1.2.1.1.2.0 = 1.3.6.1.4.1.52.3.9.1.10.7 1.3.6.1.2.1.1.4.0 =管理员 1.3.6.1.2.1.1.5.0 = els 1.3.6.1.2.1.1.3.0 = 26天,22:35:02.31 1.3.6.1.2.1.1.6.0 =机房 1.3.6.1.2.1.1.1.0 = SmartSTACK ELS100-S24TX2M 1.3.6.1.2.1.1.2.0 = 1.3.6.1.4.1.52.3.9.1.10.7 *目前,每个设备扫描仪需要一个文件。 我从ip列表中获取它们,看起来像这样。我还使用了一个小线程池来同时保留有限数量的线程。
for (String s: ips){
            output= new FileOutputStream(new File(path+s));
            threadpool.add(new DeviceScanner(s, output));
        } 
    
已邀请:
我怀疑SNMPV1Communicator(device)不是线程安全的。如我所见,它不是SNMP4j库的一部分。     
猜测这里发生了什么,尝试将所有内容放在
synchronized()
块中,如下所示:
 synchronized (DeviceScanner.class)
 {
        for (int j=0; j<num; j++){
            read= comm.snmpGetNext(oids);
            out.write(read);
            this.updateHeaders(read);

        }
        out.flush();
 }
如果这行得通,我的猜测是正确的,而您看到的问题的原因是,您有许多
OutputStreamWriter
(每个线程一个),所有写入一个single5ѭ。每个“ 4”都有自己的缓冲区。当该缓冲区已满时,它将数据传递到“ 5”。当每个
OutputStreamWriter
的缓冲区已满时,它基本上是随机的-它很可能位于一行的中间。 上面的同步块意味着一次只能将一个线程写入该线程的
OutputStreamWriter
。最后的“ 10”表示离开同步块之前,“ 4”的缓冲区应已冲刷到基础的“ 5”。 请注意,以这种方式在类对象上进行同步并不是我认为的最佳实践。您可能应该考虑使用其他某种流类的单个实例-或类似a13的类,并将所有SNMP线程的数据传递到单个文件写入线程。我已按上述方法添加了synced,因为它是您粘贴的示例代码中唯一可用于同步的内容。     
您有多个线程都使用缓冲的输出,并且都在同一个文件中。 无法保证何时安排这些线程的运行时间...输出将完全随机地排序,具体取决于线程调度。     

要回复问题请先登录注册