Naar aanleiding van mijn vorig draadje hier op p&w ben ik bezig met een producer consumer probleem. Ik had nog niet eerder met het producer/consumer pattern gewerkt, maar ik heb hem nu zo goed als helemaal door.
Wat ik graag wil hebben is het volgende:
Ik heb een object Selector, met daarin een LinkedList en een object Job. Deze selector start twee threads op, namelijk een consumer en een producer, beide met een pointer naar de LinkedList en het object Job.
Voor de duidelijkheid post ik hier de code:
De Selector: De selector start de consumer en de producer op. Aan deze twee threads worden de Job en de JobListModel meegegeven.
De bedoeling is dat de consumer de pointer Job vult met het eerste object uit de JobListModel. Dit object wordt daarbij verwijderd uit de JobListModel (queue).
Wanneer de consumer zijn werk heeft gedaan, wordt ver volgens de consumer in werking gebracht. Deze zet de Job weer achteraan in de JobListModel (queue).
De JobListModel zal ik ook even posten, maar voor zover ik kan zien werkt deze naar behoren.
Wat gaat er fout?
In de Selector wordt een nieuwe instantie van Job aangemaakt. Deze wordt meegegeven aan de consumer en producer. De gemaakte instantie is niet interessant, de bedoeling is namelijk dat deze in de eerste stap direct wordt overschreven met het eerste object uit de JobListModel. Tenminste, dat zou je verwachten. Want bij de eerste producer-cycle wordt de lijst gevuld met Job 99, die ik in de selector had geinitialiseerd.
De pointer lijkt dus niet goed te gaan. Ik heb met debuggen gekeken of in de consumer thread de _job pointer wordt gevuld met het eerste object uit de lijst. Dit gaat goed. Maar zogauw de producer verder gaat met zijn werk, wordt de lijst niet met dit object gevuld.
Mijn vraag is of iemand ziet wat er verkeerd gaat. Naar mijn weten verandert er qua pointers helemaal niks bij het werken met threads, dus ik zie het even niet meer.
Ik zal hieronder de inhoud van de lijst weergeven na de eerste 3 cycles:
Zoals je ziet wordt bij de eerste enqueue niet job 0, maar job 99 terug geplaatst. Uiteindelijk bestaat de lijst alleen uit job 99 objecten.
Ik begrijp niet wat er fout gaat, ik ben de code verschillende malen stap voor stap bij langs gegaan, maar je zou zeggen dat die pointers wel kloppen. Wie kan mij helpen?
Wat ik graag wil hebben is het volgende:
Ik heb een object Selector, met daarin een LinkedList en een object Job. Deze selector start twee threads op, namelijk een consumer en een producer, beide met een pointer naar de LinkedList en het object Job.
Voor de duidelijkheid post ik hier de code:
De Selector: De selector start de consumer en de producer op. Aan deze twee threads worden de Job en de JobListModel meegegeven.
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| public class Selector { private Job _currentJob; private JobListModel _jobListModel; public Selector() { _jobListModel = new JobListModel(); _currentJob = new Job(99,9,9,9,9); Consumer c1 = new Consumer(_jobListModel,_currentJob); Producer p1 = new Producer(_jobListModel,_currentJob); c1.start(); p1.start(); } public static void main(String[] args) { new Selector(); } } |
De bedoeling is dat de consumer de pointer Job vult met het eerste object uit de JobListModel. Dit object wordt daarbij verwijderd uit de JobListModel (queue).
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
| public class Consumer extends Thread { private JobListModel _jobListModel; private Job _job; public Consumer(JobListModel jobListModel, Job job) { _jobListModel = jobListModel; _job = job; } public void run() { for (;;) { _job = _jobListModel.dequeue(); } } } |
Wanneer de consumer zijn werk heeft gedaan, wordt ver volgens de consumer in werking gebracht. Deze zet de Job weer achteraan in de JobListModel (queue).
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| public class Producer extends Thread { private JobListModel _jobListModel; private Job _job; public Producer(JobListModel jobListModel, Job job) { _jobListModel = jobListModel; _job = job; } public void run() { for (;;) { _jobListModel.enqueue(_job); try { sleep((int)(Math.random() * 2000)); } catch (InterruptedException e) { } } } } |
De JobListModel zal ik ook even posten, maar voor zover ik kan zien werkt deze naar behoren.
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
| public class JobListModel{ private List<Job> _jobList; private boolean _available = true; public JobListModel() { _jobList = new LinkedList<Job>(); _jobList.add(new Job(0,0,0,0,0)); _jobList.add(new Job(1,10,6,1,5)); _jobList.add(new Job(2,12,1,4,2)); } public synchronized void enqueue(Job job) { if (_available == true) { try { wait(); } catch (InterruptedException e) {} } _jobList.add(job); _available = true; System.out.println("enqueue: " + job); notifyAll(); } public synchronized Job dequeue() { if (_available == false) { try { wait(); } catch (InterruptedException e) {} } _available = false; notifyAll(); System.out.println("dequeue: " + _jobList.get(0)); return _jobList.remove(0); } } |
Wat gaat er fout?
In de Selector wordt een nieuwe instantie van Job aangemaakt. Deze wordt meegegeven aan de consumer en producer. De gemaakte instantie is niet interessant, de bedoeling is namelijk dat deze in de eerste stap direct wordt overschreven met het eerste object uit de JobListModel. Tenminste, dat zou je verwachten. Want bij de eerste producer-cycle wordt de lijst gevuld met Job 99, die ik in de selector had geinitialiseerd.
De pointer lijkt dus niet goed te gaan. Ik heb met debuggen gekeken of in de consumer thread de _job pointer wordt gevuld met het eerste object uit de lijst. Dit gaat goed. Maar zogauw de producer verder gaat met zijn werk, wordt de lijst niet met dit object gevuld.
Mijn vraag is of iemand ziet wat er verkeerd gaat. Naar mijn weten verandert er qua pointers helemaal niks bij het werken met threads, dus ik zie het even niet meer.
Ik zal hieronder de inhoud van de lijst weergeven na de eerste 3 cycles:
code:
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
| na dequeue: job 0: priority 0;0 cpu cycles and 0 hdd cycles left. item 0: job 1: priority 10;6 cpu cycles and 1 hdd cycles left. item 1: job 2: priority 12;1 cpu cycles and 4 hdd cycles left. na enqueue: job 99: priority 9;9 cpu cycles and 9 hdd cycles left. item 0: job 1: priority 10;6 cpu cycles and 1 hdd cycles left. item 1: job 2: priority 12;1 cpu cycles and 4 hdd cycles left. item 2: job 99: priority 9;9 cpu cycles and 9 hdd cycles left. na dequeue: job 1: priority 10;6 cpu cycles and 1 hdd cycles left. item 0: job 2: priority 12;1 cpu cycles and 4 hdd cycles left. item 1: job 99: priority 9;9 cpu cycles and 9 hdd cycles left. na enqueue: job 99: priority 9;9 cpu cycles and 9 hdd cycles left. item 0: job 2: priority 12;1 cpu cycles and 4 hdd cycles left. item 1: job 99: priority 9;9 cpu cycles and 9 hdd cycles left. item 2: job 99: priority 9;9 cpu cycles and 9 hdd cycles left. na dequeue: job 2: priority 12;1 cpu cycles and 4 hdd cycles left. item 0: job 99: priority 9;9 cpu cycles and 9 hdd cycles left. item 1: job 99: priority 9;9 cpu cycles and 9 hdd cycles left. na enqueue: job 99: priority 9;9 cpu cycles and 9 hdd cycles left. item 0: job 99: priority 9;9 cpu cycles and 9 hdd cycles left. item 1: job 99: priority 9;9 cpu cycles and 9 hdd cycles left. item 2: job 99: priority 9;9 cpu cycles and 9 hdd cycles left. |
Zoals je ziet wordt bij de eerste enqueue niet job 0, maar job 99 terug geplaatst. Uiteindelijk bestaat de lijst alleen uit job 99 objecten.
Ik begrijp niet wat er fout gaat, ik ben de code verschillende malen stap voor stap bij langs gegaan, maar je zou zeggen dat die pointers wel kloppen. Wie kan mij helpen?