The problem is not multithreading: I wrote correctly multithreaded QuickSort in Java, and it owns standard Java sorting. I did this when I saw the giant dataset being a process, and had only one core of a 16-core machine.
One of your problems (huge) is that you are busy with the loop:
// Wait for the two other threads to finish while(!ma.finished || !mb.finished) ;
This is HUGE no-no: it is called a busy loop, and you destroy perfs.
(Another problem is that your code does not create new threads, as already indicated to you)
You need to use a different synchronization method: an example would be to use a CountDownLatch .
Another thing: there is no need to create two new threads when dividing the workload: generate only one new thread and do the second half of the current thread.
In addition, you probably do not want to create more threads than existing materials.
See my question here (asking for good open-source multi-threaded merges / quicksort / whatever). The one I use is property, I cannot insert it.
Multi-user sorting or merging
I did not implement Mergesort, but QuickSort, and I can tell you that copying arrays does not occur.
What am I doing:
- choose a fulcrum
- exchange values ​​as needed
- Have we reached the limit of flow? (depending on the number of cores)
- yes: sort the first part in this thread
- no: create a new thread
- sort the second part in the current topic
- wait for the first part to complete, if it has not already been completed (using CountDownLatch).
The code creating the new thread and creating the CountDownLatch might look like this:
final CountDownLatch cdl = new CountDownLatch( 1 ); final Thread t = new Thread( new Runnable() { public void run() { quicksort(a, i+1, r ); cdl.countDown(); } } };
The advantage of using synchronization tools such as CountDownLatch is that it is very efficient and that you do not waste time working with the low-level Java synchronization idiosync.
In your case, “split” might look like this (untested, this just gives an idea):
if ( threads.getAndIncrement() < 4 ) { final CountDownLatch innerLatch = new CountDownLatch( 1 ); final Thread t = new Merger( innerLatch, b ); t.start(); mergeSort( a ); while ( innerLatch.getCount() > 0 ) { try { innerLatch.await( 1000, TimeUnit.SECONDS ); } catch ( InterruptedException e ) {
(don’t forget to “count” the latches at each merger)
If you replaced the number of threads (up to 4 here) with the number of available cores. You can use the following (once, say, initialize some static variable at the beginning of your program: the number of cores is unlikely to change [unless you are on a machine that allows the CPU to be pumped out, as some Sun systems do):
Runtime.getRuntime().availableProcessors()