Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Многопоточный парсер, На выход поступают не все данные 
:(
    Опции темы
Padre
Дата 16.10.2011, 16:03 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 6
Регистрация: 9.5.2008

Репутация: нет
Всего: нет



Пишу многопоточный парсер.
Класс парсера выглядит следующим образом:

Код
public class Parser extends HTMLEditorKit.ParserCallback implements Runnable {
    private static List<Station> itemList = Collections.synchronizedList(new ArrayList<Item>());
    private boolean h2Tag = false;
    private int count;
    private static int threadCount = 0;

    public static List<Item> parse() {
        for (int i = 1; i <= 1000; i++) { //1000 однотипных страниц, которые нужно распарсить
            while (threadCount == 20) { //ограничиваем количество одновременно работающих потоков
                try {
                    Thread.sleep(50);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }

            Thread thread = new Thread(new Parser());
            thread.setName(Integer.toString(i));
            threadCount++; //увеличиваем количество работающих потоков
            thread.start();            
        }

        return itemList;
    }

    public void run() {
    //Здесь идет кусок кода, отвечающий за формирование ссылки на основании
    //переданного как имя потока парамера i, подключение, запуск парсинга и т.д. 
    //В общем ничего особенного. Приводить его не буду.

        threadCount--; //умешаем число работающих потоков при завершении текущего
    }

    private static void addItem(Item item) {
        itenList.add(item);
    }

    //в этом методе извлекаем нужную информацию после того, как обнаружен тег H2
    @Override
    public void handleText(char[] data, int pos) {
        if (h2Tag) {
            String itemName = new String(data).trim();

        //Item - элемент, о котором мы получаем информацию из веб-страницы
        Item item = new Item();
        item.setName(itemName);
        item.setId(count);
        addItem(item);
        
        //выводим информацию об элементе в консоль
        System.out.println(count + " = " + itemName); 
        }
    }

    @Override
    public void handleStartTag(HTML.Tag t, MutableAttributeSet a, int pos) {
        if (HTML.Tag.H2 == t) {
            h2Tag = true;
        }
    }

    @Override
    public void handleEndTag(HTML.Tag t, int pos) {
        if (HTML.Tag.H2 == t) {
            h2Tag = false;
        }
    }
}


Из другого класса парсер запускается так:

Код
List<Item> list = Parser.parse();


Все бы хорошо, но есть проблема. По завершении парсинга в итоговом списке List<Item> itemList содержится 980 элеметов, вместо 1000. Хотя в консоли их оказывается 1000. Т.е. некоторые потоки почему-то не вызывают метод addItem в методе handleText.
Я уже пытался менять тип itemList на ArrayList, CopyOnWriteArrayList, Vector. Делал метод addItem synchronized, менял его вызов на synchronized блок. Все это лишь меняет количество элементов на +-5, но итоговой тысячи получить не удается.
Также я пытался парсить меньшее количество страниц (десять). В списке не оказывается ничего, в консоли все 10.
Если многопоточность убрать, то все работает отлично, но, конечно, в разы медленнее, что не хорошо.
Если уменьшать количество одновременно работающих потоков, то количество элементов в списке приближается к желанной 1000, если увеличивать - немного удаляется от 1000. Т.е., как мне кажется, здесь явно борьба за возможность записи в список. Но тогда почему не действует синхронизация?
В чем проблема?

P.S. Также буду рад услышать просто замечания по коду.

Это сообщение отредактировал(а) Padre - 16.10.2011, 20:05
PM MAIL   Вверх
priam220
Дата 18.10.2011, 16:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 291
Регистрация: 4.6.2010

Репутация: 7
Всего: 8



добавьте:
Код

....
thread.start();
thread.join();

потоки не успевают отработать, а вы уже читаете их труды.
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.0415 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.