Heren,
Ik ben op het moment bezig met het maken van een quicksort, op het moment alleen nog voor integers maar meer dan C&P zou het niet moeten zijn voor float/doubles. De quicksort is het probleem niet (hij loopt zelfs wat sneller dan Arrays.sort(int[]) en werkt perfect, maar nu moet er eigenlijk ook een threaded variant van de quicksort komen.
Daar zitten de problemen. Ik kom er namelijk niet uit hoe ik er voor kan zorgen dat de gehele array gesorteerd is, voordat ik retourneer.
Voordat ik daar meer over kan vertellen eerst wat code.
Eerst de threadpool waar de ThreadedQuicksort gebruik van maakt. Met deze klasse tracht ik het maximaal aantal threads te beheersen en enige administratie mogelijk te maken. Tevens voorkom je natuurlijk de overhead van meerdere creëaties door Threads te hergebruiken
Als er geen threads vrij zijn en het maxAantalThreads is bereikt, dan wordt de thread op hold gezet en weer wakker gemaakt als er een thread zich weer aanmeld.
ThreadedQuicksort
De threadedquicksort sorteert de gegeven array van ints dmv het aanmaken van een InternalQuickSortJob voor elke range die gesorteerd moet worden. Echter, na het aanmaken van zo'n job, returned hij wel gelijk. Zodra quicksort() dus returned is de boel nog niet gesorteerd.
Hoe kan ik er nou voor zorgen dat bij de eerste aanroep van quicksort() de boel pas retourneerd als de array gesorteerd is?
Geprobeerd
Het volgende is geprobeerd:
• Dispatch een event vanaf de Threadpool als de boel leeg is. Echter doordat het event wordt afgehandeld in een andere thread krijg je problemen met notify() en wait()
• Gebruik join() heeft geen zin, de threads zijn volledig afgeschermd en dat moet eigenlijk zo blijven
• Ik heb bij het aanroepen van quicksort() een Semaphore op 1- p_length geinitaliseerd. Elke keer als recurse() een length van 1 of kleiner tegenkomt, geeft hij een release() op de Semaphore. quicksort() doet dan na de aanroep van een parition (welke feitelijk super.quicksort() aanroept) een aquire() waardoor hij pas kan returnen nadat alle p_length stukken een release() hebben gedaan.
Echter dan kom ik in een deathlock
Heeft iemand nog suggesties voor me? Moet de structuur om, of zie ik iets over het hoofd? Alvast bedankt voor het lezen iig
Ik ben op het moment bezig met het maken van een quicksort, op het moment alleen nog voor integers maar meer dan C&P zou het niet moeten zijn voor float/doubles. De quicksort is het probleem niet (hij loopt zelfs wat sneller dan Arrays.sort(int[]) en werkt perfect, maar nu moet er eigenlijk ook een threaded variant van de quicksort komen.
Daar zitten de problemen. Ik kom er namelijk niet uit hoe ik er voor kan zorgen dat de gehele array gesorteerd is, voordat ik retourneer.
Voordat ik daar meer over kan vertellen eerst wat code.
Eerst de threadpool waar de ThreadedQuicksort gebruik van maakt. Met deze klasse tracht ik het maximaal aantal threads te beheersen en enige administratie mogelijk te maken. Tevens voorkom je natuurlijk de overhead van meerdere creëaties door Threads te hergebruiken
Java:
Her komt er kort op neer dat als er nog threads vrij zijn, deze de gegeven job in de maag gesplitst krijgen en bij het voltooien van die job, zich weer aanmelden bij de pool.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
152
153
154
155
| import java.util.*; /** * Created by IntelliJ IDEA. * User: Glimi Development * Date: Sep 22, 2003 * Time: 6:45:59 PM * To change this template use Options | File Templates. */ public class Threadpool { private int _maxSize; private int _currentActive = 0; private List _waiting = Collections.synchronizedList( new ArrayList() ); public Threadpool( final int p_maxSize ) { initPool( p_maxSize ); setMaxSize( p_maxSize ); } synchronized public void setMaxSize( final int p_maxSize ) { if ( p_maxSize <= 0 ) throw new IllegalArgumentException( "The maxsize cannot be negative : " + p_maxSize ); _maxSize = p_maxSize; } public int getMaxSize() { return _maxSize; } public int getCurrentActive() { return _currentActive; } private void increaseCurrentActive() { ++_currentActive; } private void decreaseCurrentActive() { --_currentActive; } synchronized public void runJob( final Runnable p_job ) { final PooledThread l_thread; while ( getMaxSize() <= getCurrentActive() ) try { wait(); } catch ( InterruptedException ie ) { ie.printStackTrace(); } if ( _waiting.isEmpty() ) { l_thread = new PooledThread(); l_thread.start(); } else l_thread = (PooledThread) _waiting.get( _waiting.size() - 1 ); l_thread.wakeAndRunJob( p_job ); increaseCurrentActive(); } synchronized private boolean push( final PooledThread p_finishedThread ) { boolean l_letTreadLive = true; if ( getMaxSize() < _waiting.size() + getCurrentActive() ) l_letTreadLive = false; if ( l_letTreadLive ) { _waiting.add( _waiting.size(), p_finishedThread ); notify(); } decreaseCurrentActive(); return l_letTreadLive; } private void initPool( final int p_initialSize ) { for ( int i = 0; i < p_initialSize; ++i ) _waiting.add( i, new PooledThread() ); } class PooledThread extends Thread { private Runnable _job = null; public PooledThread() { this( null ); } public PooledThread( final Runnable p_job ) { setJob( p_job ); } private void setJob( final Runnable p_job ) { _job = p_job; } synchronized public void wakeAndRunJob( final Runnable p_job ) { setJob( p_job ); notify(); } synchronized public void run() { boolean l_stop = false; while ( !l_stop ) { // If there is no job to do, go to sleep until notifyed by wakeAndRunJob // if ( _job == null ) try { wait(); } catch ( InterruptedException ie ) { ie.printStackTrace(); continue; } // If the thread woke up and has data // if ( _job != null ) _job.run(); _job = null; l_stop = push( this ); } } } } |
Als er geen threads vrij zijn en het maxAantalThreads is bereikt, dan wordt de thread op hold gezet en weer wakker gemaakt als er een thread zich weer aanmeld.
ThreadedQuicksort
De threadedquicksort sorteert de gegeven array van ints dmv het aanmaken van een InternalQuickSortJob voor elke range die gesorteerd moet worden. Echter, na het aanmaken van zo'n job, returned hij wel gelijk. Zodra quicksort() dus returned is de boel nog niet gesorteerd.
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
| public class ThreadedQuickSort extends QuickSort { private final static int DEFAULT_MAX_SIZE = 10; private Threadpool _pool; public ThreadedQuickSort( ) { this( new Threadpool( DEFAULT_MAX_SIZE ) ); } public ThreadedQuickSort( final Threadpool p_pool ) { setPool( p_pool ); } public void setPool( final Threadpool p_pool ) { if( p_pool == null ) throw new NullPointerException( "A null Threadpool cannot be used" ); _pool = p_pool; } public Threadpool getPool( final int p_maxSize ) { return _pool; } public void quicksort( final int[] p_source, final int p_offset, final int p_length ) { super.quicksort( p_source, p_offset, p_length ); } protected void recurse( final int[] p_source, final int p_offset, final int p_length ) { if( p_length > 1) { InternalQuickSortJob l_job = new InternalQuickSortJob( p_source, p_offset, p_length); _pool.runJob( l_job ); } } private class InternalQuickSortJob implements Runnable { private int[] _source; private int _offset; private int _length; public InternalQuickSortJob( final int[] p_source, final int p_offset, final int p_length ) { _source = p_source; _offset = p_offset; _length = p_length; } public void run(){ quicksort( _source, _offset, _length); } } } |
Hoe kan ik er nou voor zorgen dat bij de eerste aanroep van quicksort() de boel pas retourneerd als de array gesorteerd is?
Geprobeerd
Het volgende is geprobeerd:
• Dispatch een event vanaf de Threadpool als de boel leeg is. Echter doordat het event wordt afgehandeld in een andere thread krijg je problemen met notify() en wait()
• Gebruik join() heeft geen zin, de threads zijn volledig afgeschermd en dat moet eigenlijk zo blijven
• Ik heb bij het aanroepen van quicksort() een Semaphore op 1- p_length geinitaliseerd. Elke keer als recurse() een length van 1 of kleiner tegenkomt, geeft hij een release() op de Semaphore. quicksort() doet dan na de aanroep van een parition (welke feitelijk super.quicksort() aanroept) een aquire() waardoor hij pas kan returnen nadat alle p_length stukken een release() hebben gedaan.
Echter dan kom ik in een deathlock
Heeft iemand nog suggesties voor me? Moet de structuur om, of zie ik iets over het hoofd? Alvast bedankt voor het lezen iig