9 / 9 / 3
Регистрация: 03.03.2015
Сообщений: 78
1

Разделение разбора xml-файла и обработка полученных данных на независимые потоки

17.10.2015, 17:54. Показов 1357. Ответов 9
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
файл разбирается при помощи StAX.
разобранные данные записываются в ArrayList. для их обработки они вытаскиваются из этого же ArrayList.
когда разбиваю это на два потока, то в потоке обработки ArrayList существует, но его size равно 0, соответственно никакая обработка данных не происходит.
подскажите куда смотреть, чтоб сделать как надо.
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.10.2015, 17:54
Ответы с готовыми решениями:

Консольное приложение для периодического опроса XML файла и записи полученных данных в базу SQLlite
Необходимо сделать консольное приложение для периодического опросаXML файла и записи полученных...

Обработка данных XML-файла
Добрый день! В очередной раз застряла на ерундовом вопросе, надеюсь, что смогу получить у Вас...

Классы и методы для разбора XML файла
Подскажите какой класс или модуль подключить, какие обьекты создавать/вызывать, функции и методы....

Обработка полученных данных.
Я сделал сервер на чистых WinSock1. Потом принимаю данные. char str; err = recv(s1, str,...

9
Эксперт Java
4092 / 3826 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 11
17.10.2015, 18:11 2
sskdroid, ArrayList не потокобезопасная коллекция, и скорее всего его нельзя использовать так как это делаете. Попробуйте заменить на какую-нибудь ConcurrentQueue, например на LinkedBlockingQueue.
Больше без кода сложно что-то сказать
1
9 / 9 / 3
Регистрация: 03.03.2015
Сообщений: 78
17.10.2015, 18:44  [ТС] 3
turbanoff , ну я пробовал с Vector, картина та же самая. есть чувство, что там что-то принципиально не то, нужно добавлять какую-то конструкцию или логику, о которой я в силу неопытности пока не догадываюсь. вот основной код:

Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
public class TestTaskThread implements XMLStreamConstants {
    public static void main(String[] args){
     
        new InputThread().start();
        new OutThread().start();
 
    }
 
    private static class InputThread extends Thread{
        public void run(){
            TestTaskThread handler = new TestTaskThread();
            try{
                FileInputStream inStream = new FileInputStream("\\test.xml");
                XMLStreamReader xmlReader = XMLInputFactory.newInstance().createXMLStreamReader(inStream);
                int event;
                while (xmlReader.hasNext()) {
                    event = xmlReader.next();
                    switch (event){
                        case START_ELEMENT: handler.processElement(xmlReader); break;
                        case CHARACTERS: handler.processText(xmlReader.getText()); break;
                        case END_ELEMENT: handler.finishElement(xmlReader.getLocalName()); break;
                    }
                }
                xmlReader.close();
            }catch(Exception ex){
                System.out.println("Введите путь к xml-файлу с входными данными, удовлетворяющими xsd-схеме.");
            }
        }
    }
 
    private static class OutThread extends Thread{
        public void run(){
            try{
                for (Figure figure : figures){
                    /*В зависимости от значения figure.getTypeFigure(), которое является названием фигуры,
                    выбирается соответствующий метод для подсчета площади.*/
                    switch (figure.getTypeFigure()){
                        case "triangle": areaTriangle(figure.getArrayValues().get(0), figure.getArrayValues().get(1), figure.getArrayValues().get(2)); break;
                        case "rectangle": areaRectangle(figure.getArrayValues().get(0), figure.getArrayValues().get(1)); break;
                        case "square": areaSquare(figure.getArrayValues().get(0)); break;
                        case "circle": areaCircle(figure.getArrayValues().get(0));
                    }
                    color = figure.getColor();
                    System.out.println(count++ + ": " + color + " - " + (double)Math.round(area*100)/100);
                }
                Thread.sleep(0);
            }catch(InterruptedException ie){System.out.println("Error");}
        }
    }
...
Добавлено через 12 минут
"LinkedBlockingQueue<E> — Блокирующая очередь на связанных нодах, реализованная на «two lock queue» алгоритме: один лок на добавление, другой на вытаскивание элемента."

то есть один поток работает на добавление, второй на вытаскивание и чтоб это работало нужна строгая очередность? и это соответствует определению "независимые потоки"?
0
Эксперт Java
4092 / 3826 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 11
18.10.2015, 00:50 4
sskdroid, Очередь нужна просто чтобы разграничить потоки между собой.
Само использование очереди обычно минимально и не вносит задержек: несколько потоков что-нибудь туда быстро кладут, другие несколько потоков быстро вытаскивают и долго обрабатывают. Так что неважно сколько там локов внутри и как она работает.

PS. По вашему коду ничего не понятно. Как потоки между собой общаются? Где ArrayList?
1
9 / 9 / 3
Регистрация: 03.03.2015
Сообщений: 78
18.10.2015, 05:38  [ТС] 5
вот полностью код.
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
package ru.ssk.testtask;
 
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.concurrent.LinkedBlockingQueue;
 
/**
 * Created by ssk on 17.10.2015.
 */
 
public class TestTaskThread implements XMLStreamConstants {
    public static void main(String[] args){
        new InputThread().start();
        new OutThread().start();
    }
 
    private static class InputThread extends Thread{
        public void run(){
            TestTaskThread handler = new TestTaskThread();
            try{
                FileInputStream inStream = new FileInputStream("\\test.xml");
                XMLStreamReader xmlReader = XMLInputFactory.newInstance().createXMLStreamReader(inStream);
                int event;
                while (xmlReader.hasNext()) {
                    event = xmlReader.next();
                    switch (event){
                        case START_ELEMENT: handler.processElement(xmlReader); break;
                        case CHARACTERS: handler.processText(xmlReader.getText()); break;
                        case END_ELEMENT: handler.finishElement(xmlReader.getLocalName()); break;
                    }
                }
                xmlReader.close();
            }catch(Exception ex){
                System.out.println("Введите путь к xml-файлу с входными данными, удовлетворяющими xsd-схеме.");
            }
        }
    }
 
    private static class OutThread extends Thread{
        public void run(){
            try{
                for (Figure figure : figures){
                    /*В зависимости от значения figure.getTypeFigure(), которое является названием фигуры,
                    выбирается соответствующий метод для подсчета площади.*/
                    switch (figure.getTypeFigure()){
                        case "triangle": areaTriangle(figure.getArrayValues().get(0), figure.getArrayValues().get(1), figure.getArrayValues().get(2)); break;
                        case "rectangle": areaRectangle(figure.getArrayValues().get(0), figure.getArrayValues().get(1)); break;
                        case "square": areaSquare(figure.getArrayValues().get(0)); break;
                        case "circle": areaCircle(figure.getArrayValues().get(0));
                    }
                    color = figure.getColor();
                    System.out.println(count++ + ": " + color + " - " + (double)Math.round(area*100)/100);
                }
                Thread.sleep(0);
            }catch(InterruptedException ie){System.out.println("Error");}
        }
    }
 
    static String color;
    private static double area;
    private static int count = 1;
    private boolean inColor, inValue;
    private static Figure figure;
    private static LinkedBlockingQueue<Figure> figures = new LinkedBlockingQueue<>();
 
    private void processElement(XMLStreamReader element) throws XMLStreamException {
        switch (element.getLocalName()){
            case "triangle":
            case "rectangle":
            case "square":
            case "circle": figure = new Figure(); break;
            case "side":
            case "diameter": inValue = true; break;
            case "color": inColor = true;
        }
    }
 
    private void processText(String text){
        if (inColor){
            figure.setColor(text);
            inColor = false;
        }else if (inValue){
            figure.setValue(Double.parseDouble(text));
            inValue = false;
        }
    }
 
    private void finishElement(String name){
        switch (name){
            case "triangle":
                figure.setTypeFigure("triangle");
                addAndNullFigure(); break;
            case "rectangle":
                figure.setTypeFigure("rectangle");
                addAndNullFigure(); break;
            case "square":
                figure.setTypeFigure("square");
                addAndNullFigure(); break;
            case "circle":
                figure.setTypeFigure("circle");
                addAndNullFigure();
        }
    }
 
    private void addAndNullFigure(){
        //Экземпляр класса Figure добавляется в коллекцию figures
        figures.add(figure);
        figure = null;
    }
 
    private static double areaTriangle(double a, double b, double c){
        double p = (a+b+c)/2;
        area = Math.sqrt(p*(p-a)*(p-b)*(p-c));
        return area;
    }
 
    private static double areaRectangle(double a, double b){
        area = a*b;
        return area;
    }
 
    private static double areaSquare(double a){
        area = a*a;
        return area;
    }
 
    private static double areaCircle(double a){
        area = Math.PI*a*a/4;
        return area;
    }
 
    private class Figure{
        private String color;
        private String typeFigure;
        private ArrayList<Double> arrayValues = new ArrayList<>();
 
        public ArrayList<Double> getArrayValues() {return arrayValues;}
        public void setValue(Double text) {arrayValues.add(text);}
 
        public String getColor() {return color;}
        public void setColor(String color) {this.color = color;}
 
        public String getTypeFigure() {return typeFigure;}
        public void setTypeFigure(String typeFigure) {this.typeFigure = typeFigure;}
    }
 
}
потоки никак не общаются между собой. а как они должны общаться? ArrayList заменил на LinkedBlockingQueue, картина та же. то есть начинает работать поток обработки данных, а коллекция с которой он должен работать пустая. или он ее как-то регулярно обновлять что ли должен..
0
206 / 206 / 71
Регистрация: 25.02.2014
Сообщений: 569
18.10.2015, 10:16 6
sskdroid, в методе run() OutThread'a, поставьте безконечный цикл, и извлекайте элементы, методами которые для этого предназначены, а не форичем
1
9 / 9 / 3
Регистрация: 03.03.2015
Сообщений: 78
19.10.2015, 15:17  [ТС] 7
да, LinkedBlockingQueue, бесконечный цикл, метод take() - вытащить и удалить первый элемент, и все работает)
теперь я пытаюсь придумать как сделать без бесконечного цикла, а то не дело, когда поток висит такой.
как я понимаю, останавливать цикл, если size() коллекции = 0 не пойдет, поскольку поток на вытаскивание может опередить поток, который кладет элементы?

или не может опередить, если поток который кладет запускается раньше? тестирую на большом файле, когда начинает работать поток на Out в коллекции уже 300 элементов
0
206 / 206 / 71
Регистрация: 25.02.2014
Сообщений: 569
19.10.2015, 15:45 8
sskdroid, условием выхода должно быть то, что коллекция пустая и первый поток завершен
1
9 / 9 / 3
Регистрация: 03.03.2015
Сообщений: 78
19.10.2015, 16:15  [ТС] 9
Kochmarik, действительно, очевидно.
0
Эксперт Java
4092 / 3826 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 11
19.10.2015, 18:23 10
sskdroid, Есть еще популярная техника (Poison Pill), чтобы остановить Consumer-ов очереди - добавлять в конце обработки элемент-маркер конца очереди.
А в потоке, который читает из очереди, проверять то, что он достал.
В вашем случае, например, можно добавлять Figure с typeFigure = null.
1
19.10.2015, 18:23
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
19.10.2015, 18:23
Помогаю со студенческими работами здесь

Обработка полученных данных с COM порта
Доброго всем времени суток. Вопрос такого плана - есть некое устройство посылающее данные в COM...

Vk api обработка полученных данных
Доброе время суток Дорогие знатоки подскажите пожалуйста как можно обработать данные полученные...

Обработка данных, полученных из COM-порта
В текстовом файле одна строка с данными полученными из СОМ порта(файл REG.jpg). Ее надо обработать,...

Обработка данных полученных из SerialPort
Добрый день. подскажите пожалуйста как решить следующую задачу? На VB.NET в ком порт нужно...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
10
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru