Einen guten Tag...
Ich habe heute den Sortieralgorithmus MergeSort auf Zahlen geschrieben.
Dieser arbeitet mit Vectoren, die zuerst in der Rekursion aufgeteilt werden, sortiert zusammengefasst werden, bis schließlich das angeforderte sortiert ist...
Alles klappt wunderbar... Ich dachte mir aber, wenn ich Threads laufen lasse, womit ich diese 'Unteraufteilung / Sortierung', die nicht voneinander abhängen, gleichzeitig von statten bringe, wäre die Aktion viel schneller fertig, und man müsste nicht immer alles Schritt für Schritt machen...
Zu meiner Überraschung stellte sich genau das Gegenteil heraus: Mit Threads dauert alles 15 mal so lange... (Bei ca. 4050 Einträgen: ~680-800 Millisekunden, Threadlos: ~30 Millisekunden)
Den Sortiervorgang selber, also zwei sortierte Listen in eine sortierte Liste einzufügen, ist bei beiden Vorgängen / Klassen gleich.
Der Unterschied liegt nur darin, dass beim einen die Unterteilung und der Splittvorgang im Thread ausgeführt wird, der, wenn nötig, auf einen anderen Thread wartet, bis dieser fertig ist, auch wenn nötig.
Hier mal ein Quellcode:
<< Dieser Auszug is bei beiden Klassen gleich...
Klasse mit Threads:
Klasse ohne Threads (wesentlich kürzer):
Habe ich vielleicht einen Fehler im Quellcode, der alles umsonst bremst? Oder liegt das daran, dass einen Thread zu starten enorm viel mehr Zeit kostet, als einfach alles nacheinander zu machen?
Danke für euren Tipp!
Muja
Ich habe heute den Sortieralgorithmus MergeSort auf Zahlen geschrieben.
Dieser arbeitet mit Vectoren, die zuerst in der Rekursion aufgeteilt werden, sortiert zusammengefasst werden, bis schließlich das angeforderte sortiert ist...
Alles klappt wunderbar... Ich dachte mir aber, wenn ich Threads laufen lasse, womit ich diese 'Unteraufteilung / Sortierung', die nicht voneinander abhängen, gleichzeitig von statten bringe, wäre die Aktion viel schneller fertig, und man müsste nicht immer alles Schritt für Schritt machen...
Zu meiner Überraschung stellte sich genau das Gegenteil heraus: Mit Threads dauert alles 15 mal so lange... (Bei ca. 4050 Einträgen: ~680-800 Millisekunden, Threadlos: ~30 Millisekunden)
Den Sortiervorgang selber, also zwei sortierte Listen in eine sortierte Liste einzufügen, ist bei beiden Vorgängen / Klassen gleich.
Der Unterschied liegt nur darin, dass beim einen die Unterteilung und der Splittvorgang im Thread ausgeführt wird, der, wenn nötig, auf einen anderen Thread wartet, bis dieser fertig ist, auch wenn nötig.
Hier mal ein Quellcode:
Java:
public class Algorithm
{
Vector<Integer> toMerge = new Vector<Integer>();
public Algorithm()
{
toMerge.addElement(new Integer(3));
toMerge.addElement(new Integer(2));
toMerge.addElement(new Integer(44));
toMerge.addElement(new Integer(5));
toMerge.addElement(new Integer(4));
[...]
}
public Vector<Integer> sort(Vector<Integer> firstSorted, Vector<Integer> secondSorted)
{
int fusionedLength = firstSorted.size() + secondSorted.size();
Vector<Integer> fusioned = new Vector<Integer>();
for(int i=0; i<fusionedLength; i++)
if(secondSorted.size() == 0 && firstSorted.size() > 0 || firstSorted.size() > 0 && firstSorted.get(0) <= secondSorted.get(0))
fusioned.addElement(firstSorted.remove(0));
else
fusioned.addElement(secondSorted.remove(0));
return fusioned;
}
Klasse mit Threads:
Java:
public Algorithm()
{
[...]
toMerge.addElement(new Integer(10));
System.out.println(toMerge.size());
long start = new Date().getTime();
System.out.println(start);
Thread sortThread = new Thread(new SortThread(toMerge, this));
sortThread.start();
try
{
sortThread.join();
} catch (InterruptedException e)
{
e.printStackTrace();
}
System.out.println(toMerge);
long end = new Date().getTime();
System.out.println(end);
long duration = end-start;
System.out.println("Dauer: " + duration);
}
class SortThread implements Runnable
{
Vector<Integer> toSort = null;
Vector<Integer> firstPart = null;
Vector<Integer> secondPart = null;
SortThread starterThread = null;
Algorithm starter = null;
boolean first = false;
SortThread(Vector<Integer> toSort, SortThread starterThread, boolean first)
{
this.first = first;
this.toSort = toSort;
this.starterThread = starterThread;
}
SortThread(Vector<Integer> toSort, Algorithm starterThread)
{
this.toSort = toSort;
this.starter = starterThread;
}
public void run()
{
int toSortLength = toSort.size();
firstPart = new Vector<Integer>();
secondPart = new Vector<Integer>();
for(int i=0; i<toSortLength; i++)
if(i%2 == 0)
firstPart.addElement(toSort.get(i));
else
secondPart.addElement(toSort.get(i));
Thread firstPartThread = null;
int firstPartLength = firstPart.size();
if(firstPartLength > 1)
{
firstPartThread = new Thread(new SortThread(firstPart, this, true));
firstPartThread.start();
}
Thread secondPartThread = null;
int secondPartLength = secondPart.size();
if(secondPartLength > 1)
{
secondPartThread = new Thread(new SortThread(secondPart, this, false));
secondPartThread.start();
}
try
{
if(firstPartThread != null)
firstPartThread.join();
if(secondPartThread != null)
secondPartThread.join();
} catch(InterruptedException e)
{
e.printStackTrace();
}
toSort = sort(firstPart, secondPart);
if(starterThread != null)
if(first)
starterThread.firstPart = toSort;
else
starterThread.secondPart = toSort;
else
starter.toMerge = toSort;
}
}
Klasse ohne Threads (wesentlich kürzer):
Java:
public Algorithm()
{
[...]
toMerge.addElement(new Integer(10));
long start = new Date().getTime();
System.out.println(start);
toMerge = merge(toMerge);
System.out.println(toMerge);
long end = new Date().getTime();
System.out.println(end);
long duration = end-start;
System.out.println("Dauer: " + duration);
}
public Vector<Integer> merge(Vector<Integer> toSort)
{
int toSortLength = toSort.size();
Vector<Integer> firstPart = new Vector<Integer>();
Vector<Integer> secondPart = new Vector<Integer>();
for(int i=0; i<toSortLength; i++)
if(i%2 == 0)
firstPart.addElement(toSort.get(i));
else
secondPart.addElement(toSort.get(i));
int firstPartLength = firstPart.size();
if(firstPartLength > 1)
firstPart = merge(firstPart);
int secondPartLength = secondPart.size();
if(secondPartLength > 1)
secondPart = merge(secondPart);
Vector<Integer> sorted = new Vector<Integer>();
sorted = sort(firstPart, secondPart);
return sorted;
}
Habe ich vielleicht einen Fehler im Quellcode, der alles umsonst bremst? Oder liegt das daran, dass einen Thread zu starten enorm viel mehr Zeit kostet, als einfach alles nacheinander zu machen?
Danke für euren Tipp!
Muja