Многопоточный Java I / 0 и проблема связи - PullRequest
1 голос
/ 15 апреля 2011

Я использую Java для создания приложения для управления сетью.В этом приложении я устанавливаю связь с сетевыми устройствами, используя библиотеку SNMP4j (для протокола snmp).Итак, я должен сканировать определенные значения сетевых устройств, используя этот протокол, и поместить результат в файл для кеширования.В какой-то момент я решил сделать свое приложение многопоточным и назначить устройство потоку.Я создал класс, который реализует работающий интерфейс, а затем сканирует значения, которые я хочу для каждого устройства.

Когда я запускаю этот класс в одиночку, он работает нормально.но когда я помещаю несколько потоков одновременно, вывод выводит из строя, он выводит дополнительные или не по порядку выходные данные в файлы.Теперь мне интересно, связана ли эта проблема с вводом / выводом или с коммуникацией.

Здесь я приведу часть кода, чтобы вы могли видеть, что я делаю, и помогать мне понять, что не так.

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 = admin

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 = admin

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, похоже, это.Я также использую небольшой пул потоков, чтобы сохранить ограниченное количество потоков одновременно.

<code>
for (String s: ips){
            output= new FileOutputStream(new File(path+s));
            threadpool.add(new DeviceScanner(s, output));
        } 

Ответы [ 3 ]

1 голос
/ 15 апреля 2011

Делая дикие предположения о том, что здесь происходит, попробуйте поместить все в блок synchronized(), например:

 synchronized (DeviceScanner.class)
 {
        for (int j=0; j&lt;num; j++){
            read= comm.snmpGetNext(oids);
            out.write(read);
            this.updateHeaders(read);

        }
        out.flush();
 }

Если это работает, я думаю, что это правильно, и причина проблем, с которыми вы сталкиваетесь, заключается в том, что у вас есть много OutputStreamWriter с (по одному в каждом потоке), все пишут в один OutputStream. Каждый OutputStreamWriter имеет свой собственный буфер. Когда этот буфер заполнен, он передает данные в OutputStream. По сути, это случайный случай, когда каждый буфер OutputStreamWriter заполнен - ​​он вполне может быть в середине строки.

Синхронизированный блок выше означает, что только один поток одновременно может записывать в этот поток OutputStreamWriter. Символ flush() в конце означает, что перед тем, как покинуть синхронизированный блок, буфер OutputStreamWriter должен быть очищен до базового OutputStream.

.

Обратите внимание, что такая синхронизация на объекте класса - это не то, что я бы посоветовал. Вероятно, вам следует рассмотреть возможность использования одного экземпляра какого-либо другого класса потока - или что-то вроде LinkedBlockingQueue, когда все потоки SNMP передают свои данные в один поток записи файлов. Я добавил синхронизированный, как указано выше, потому что это была единственная доступная синхронизация в вашем вставленном примере кода.

1 голос
/ 15 апреля 2011

Я подозреваю, что SNMPV1Communicator (устройство) не является поточно-ориентированным.Как я вижу, это не часть библиотеки SNMP4j.

0 голосов
/ 15 апреля 2011

У вас есть несколько потоков, использующих буферизованный вывод и один и тот же файл.

Нет никаких гарантий относительно того, когда эти потоки будут запланированы для запуска ... выходные данные будут располагаться в довольно случайном порядке, что определяется планированием потоков.

...