Threads Multithreading

deppensido

Mitglied
Hallo,
ich soll folgenden Quellcode per Multithreading optimieren.
Der Code erzeugt ein Zufallsarray und sortiert es mit mergesort.
Meine Aufgabe ist nun in der Methode sort() dynamisch viele
Threads zur Verfügung zu stellen (was ich glaube schon gemacht zu haben)
und diese dann sinnvoll auf die Sortieraufgabe zu verteilen.
Aber, wie kann ich jetzt jeden Thread sagen, was er machen soll?
Jede Hilfe ist willkommen.

Gruß Volker

Java:
import java.util.Random;
import java.lang.Runtime;
import sun.misc.RequestProcessor;

public class Exercise2 extends Thread {
	public static Random random = new Random(100);
	
	public static void main(String[] args) throws InterruptedException {
		int[] array = createRandomArray(10000000);
		
		long time = System.currentTimeMillis();
		
		int[] sortedArray = sort(array);
		
		if(sortedArray.length != array.length || !isSorted(sortedArray)) {
			System.err.println("Failed to sort given array! :-(");
			return;
		}		
		System.out.println("Success! Sorting took " + (System.currentTimeMillis() - time) + "ms.");		
	}

	/**
	 * Creates a randomly filled array of given length
	 * @param length
	 * @return
	 */
	private static int[] createRandomArray(int length) {
		int[] result = new int[length];
		for(int i = 0; i < length; i++) {
			result[i] = random.nextInt();
		}
		return result;
	}
	
	/**
	 * Checks whether a given int array is sorted in ascending order  
	 * @param array
	 * @return <code>true</code> if the given int array is sorted; <code>false</code> otherwise.
	 */
	private static boolean isSorted(int[] array) {
		for(int i = 1; i < array.length; i++) {
			if(array[i] < array[i-1]) {
				return false;
			}
		}
		return true;
	}
	
	/**
	 * Merges two sorted int array into one new sorted array.
	 * @param lhs
	 * @param rhs
	 * @return
	 */
	private static int[] merge(int[] lhs, int[] rhs) {
		int[] result = new int[lhs.length + rhs.length];
		
		int leftIndex = 0;
		int rightIndex = 0;
		while(leftIndex < lhs.length && rightIndex < rhs.length) {
			if(lhs[leftIndex] <= rhs[rightIndex]) {
				result[leftIndex + rightIndex] = lhs[leftIndex];
				leftIndex++;
			} else {
				result[leftIndex + rightIndex] = rhs[rightIndex];
				rightIndex++;
			}
		}
		
		while(leftIndex < lhs.length) {
			result[leftIndex + rightIndex] = lhs[leftIndex];
			leftIndex++;
		}
		
		while(rightIndex < rhs.length) {
			result[leftIndex + rightIndex] = rhs[rightIndex];
			rightIndex++;
		}
		
		return result;
	}
	
	/**
	 * Sorts an array from index <code>startIndex</code> (inclusive) to <code>endIndex</code> (exclusive).
	 * @param array
	 * @param startIndex
	 * @param endIndex
	 * @return new array that is sorted
	 */
	private static int[] mergeSort(int[] array, int startIndex, int endIndex) {
		int length = endIndex - startIndex;
		if(length == 0) {
			return new int[]{};
		}
		if(length == 1) {
			return new int[]{array[startIndex]};
		}
		
		int halfLength = length / 2;
		int[] sortedLeftPart = mergeSort(array, startIndex, startIndex + halfLength);
		int[] sortedRightPart = mergeSort(array, startIndex + halfLength, endIndex);
		
		return merge(sortedLeftPart, sortedRightPart);		
	}
	
	
	/**
	 * Sorts a given array (ascending order)
	 * @param array
	 * @return
	 */
	private synchronized static int[] sort(int[] array) throws InterruptedException {
        //TODO: use multiple threads to speed up the sorti
            Runtime runtime = Runtime.getRuntime();
            int anzahl = runtime.availableProcessors();
            Thread[] thread = new Thread[anzahl];
           
          
            return mergeSort(array, 0, array.length);
	}
        
        @Override
        public void run() {
            
        }
}
 

Volvagia

Top Contributor
Du schreibst es in die run(able) rein. Mergesort besteht ja daraus, die Liste in mehrere kleinere Listen zu zerlegen, diese zu sortieren und dann einfach der Reihe nach zusammenzuführen. Zerlege die Liste zuerst Singlethread in mehrere anderen, übergib jeden der Threads eine der Listen (oder zerlege weiter, wenn sie noch groß genug sind), und übergib jeden Thread eine Liste. Starte dann die Threads per #start und warte auf sie per #join. Dann kannst du dir die Listen wieder abhohlen und zusammenführen. Achte nur darauf, dass du nicht in zu kleine Listen aufteilst, sonst bremst der Overhead der Threaderstellung und -startung zu sehr aus.
 

Volvagia

Top Contributor
Auch wenn ichs nicht getestet habe, müsste das wohl funktionieren.

Java:
public class MergeSort
{
	private static final int ARRAY_SIZE = 10000000;
	private static final int ARRAY_PARTS = 2;
	
	public static void main(String[] args)
	{
		int[] arrayToSort = generateRandArray();
		int[][] splitArray = splitArray(arrayToSort);
		
		Thread[] t = new Thread[splitArray.length];
		for(int i = 0; i < splitArray.length; i++)
		{
			t[i] = new SortThread(splitArray[i]);
			t[i].start();
		}
		for(int i = 0; i < splitArray.length; i++)
		{
			try
			{
				t[i].join();
			}
			catch (InterruptedException e) {}
		}
		merge(splitArray);		
	}
	private static int[] generateRandArray()
	{
		//TODO Hier Array generieren
		return(new int[ARRAY_SIZE]);
	}
	private static int[][] splitArray(int[] arrayToSort)
	{
		//Hier splitten
		return null;
	}
	private static void merge(int[][] splitArray)
	{
		//TODO Hier zusammenfügen.
	}
	private static class SortThread extends Thread
	{
		private int[] array; 
		
		public SortThread(int[] splitArray)
		{
			super("SortThread");
			array = splitArray;
		}
		public void run()
		{
			sort();
		}
		private void sort()
		{
			//TODO Hier sortieren.
		}
	}
}
 

deppensido

Mitglied
Hallo,

ich soll aber die Klasse so lassen (siehe Code vom ersten Beitrag)
und dann in der Methode sort dynamisch so viele Threads erstellen,
wie in der Java-VM Prozesse zur Verfügung stehen und diese dann
gleichmäßig auf die Sortieraufgabe verteilen.
Hab dazu jetzt folgenden Code:
Wie muss ich denn jetzt die Klasse WorkThread implementieren.
Ich denke die Klasse Exercise2 kann so bleiben.

Gruß Volker
Java:
import java.util.Random;

public class Exercise2 {
	public static Random random = new Random(100);
	
	public static void main(String[] args) throws InterruptedException {
		int[] array = createRandomArray(10000000);
		
		long time = System.currentTimeMillis();
		
		int[] sortedArray = sort(array);
		
		if(sortedArray.length != array.length || !isSorted(sortedArray)) {
			System.err.println("Failed to sort given array! :-(");
			return;
		}		
		System.out.println("Success! Sorting took " + (System.currentTimeMillis() - time) + "ms.");		
	}

	/**
	 * Creates a randomly filled array of given length
	 * @param length
	 * @return
	 */
	private static int[] createRandomArray(int length) {
		int[] result = new int[length];
		for(int i = 0; i < length; i++) {
			result[i] = random.nextInt();
		}
		return result;
	}
	
	/**
	 * Checks whether a given int array is sorted in ascending order  
	 * @param array
	 * @return <code>true</code> if the given int array is sorted; <code>false</code> otherwise.
	 */
	private static boolean isSorted(int[] array) {
		for(int i = 1; i < array.length; i++) {
			if(array[i] < array[i-1]) {
				return false;
			}
		}
		return true;
	}
	
	/**
	 * Merges two sorted int array into one new sorted array.
	 * @param lhs
	 * @param rhs
	 * @return
	 */
	private static int[] merge(int[] lhs, int[] rhs) {
		int[] result = new int[lhs.length + rhs.length];
		
		int leftIndex = 0;
		int rightIndex = 0;
		while(leftIndex < lhs.length && rightIndex < rhs.length) {
			if(lhs[leftIndex] <= rhs[rightIndex]) {
				result[leftIndex + rightIndex] = lhs[leftIndex];
				leftIndex++;
			} else {
				result[leftIndex + rightIndex] = rhs[rightIndex];
				rightIndex++;
			}
		}
		
		while(leftIndex < lhs.length) {
			result[leftIndex + rightIndex] = lhs[leftIndex];
			leftIndex++;
		}
		
		while(rightIndex < rhs.length) {
			result[leftIndex + rightIndex] = rhs[rightIndex];
			rightIndex++;
		}
		
		return result;
	}
	
	/**
	 * Sorts an array from index <code>startIndex</code> (inclusive) to <code>endIndex</code> (exclusive).
	 * @param array
	 * @param startIndex
	 * @param endIndex
	 * @return new array that is sorted
	 */
	private static int[] mergeSort(int[] array, int startIndex, int endIndex) {
		int length = endIndex - startIndex;
		if(length == 0) {
			return new int[]{};
		}
		if(length == 1) {
			return new int[]{array[startIndex]};
		}
		
		int halfLength = length / 2;
		int[] sortedLeftPart = mergeSort(array, startIndex, startIndex + halfLength);
		int[] sortedRightPart = mergeSort(array, startIndex + halfLength, endIndex);
		
		return merge(sortedLeftPart, sortedRightPart);		
	}
	
	
	/**
	 * Sorts a given array (ascending order)
	 * @param array
	 * @return
	 */
	private synchronized static int[] sort(int[] array) throws InterruptedException {
        //TODO: use multiple threads to speed up the sorting
            Runtime runtime = Runtime.getRuntime();
            int anzahl = runtime.availableProcessors();
                    
            Thread[] thread = new Thread[anzahl];
            for(Thread t : thread) {
                t = new WorkThread(array);
                t.start();
            }
            for(Thread t : thread)
                t.join();
            return mergeSort(array, 0, array.length);
	}

        private static class WorkThread extends Thread {
            private int[] array;
            public WorkThread(int[] array) {
                this.array = array;
            }
            @Override
            public void run() {

            }
        }
}
 

Volvagia

Top Contributor
Sieht (vom Syntax her) schon richtig aus. Nur musst du das zu sortierende Array noch splitten und die einzelnen Parts den verschiedenen Threads übergeben, damit jeder seinen Teil bearbeitet, und in der run() der Threads sortieren.
 

deppensido

Mitglied
Hallo,
hab nun versucht das Array auf zu splitten.
Hinter wird es wieder mit der Methode merge zusammengeführt.
Aber die Sortierung funktioniert nicht.

Gruß Volker
Java:
 private synchronized int[] sortLeftPart(int[] array, int startIndex, int endIndex) {
                int length = endIndex - startIndex;
		if(length == 0) {
			return new int[]{};
		}
		if(length == 1) {
			return new int[]{array[startIndex]};
                }
                int halfLength = length / 2;
                return sortLeftPart(array, startIndex, startIndex + halfLength);
            }

            private synchronized int[] sortRightPart(int[] array, int startIndex, int endIndex) {
                int length = endIndex - startIndex;
		if(length == 0) {
			return new int[]{};
		}
		if(length == 1) {
			return new int[]{array[startIndex]};
                }
                int halfLength = length / 2;
                return sortRightPart(array, startIndex + halfLength, endIndex);
            }
 

deppensido

Mitglied
hallo,

hab jetzt folgende Lösung, aber funktionieren tut das immer noch nicht.
Es kann nur an der Methode sort, split und der Klasse Workthread liegen,
da der Rest vorgegeben war. Mir fliegt in der main Methode und der Sort Methode
der Exercise 2 Klasse Nullpointer Exceptions um die Ohren.
Ich hoffe mir kann jemand helfen die Fehler zu beseitigen.

Gruß Volker

Java:
package gp2.ha5.exercise2;

import java.util.ArrayList;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Exercise2 {

    public static Random random = new Random(100);

    public static void main(String[] args) throws InterruptedException {

        int[] array = createRandomArray(10000000);

        long time = System.currentTimeMillis();

        int[] sortedArray = sort(array);

        if (sortedArray.length != array.length || !isSorted(sortedArray)) {
            System.err.println("Failed to sort given array! :-(");
            return;
        }
        System.out.println("Success! Sorting took " + (System.currentTimeMillis() - time) + "ms.");
    }

    /**
     * Creates a randomly filled array of given length
     * @param length
     * @return
     */
    private static int[] createRandomArray(int length) {
        int[] result = new int[length];
        for (int i = 0; i < length; i++) {
            result[i] = random.nextInt();
        }
        return result;
    }

    /**
     * Checks whether a given int array is sorted in ascending order
     * @param array
     * @return <code>true</code> if the given int array is sorted; <code>false</code> otherwise.
     */
    private static boolean isSorted(int[] array) {
        for (int i = 1; i < array.length; i++) {
            if (array[i] < array[i - 1]) {
                return false;
            }
        }
        return true;
    }

    /**
     * Merges two sorted int array into one new sorted array.
     * @param lhs
     * @param rhs
     * @return
     */
    private static int[] merge(int[] lhs, int[] rhs) {
        int[] result = new int[lhs.length + rhs.length];

        int leftIndex = 0;
        int rightIndex = 0;
        while (leftIndex < lhs.length && rightIndex < rhs.length) {
            if (lhs[leftIndex] <= rhs[rightIndex]) {
                result[leftIndex + rightIndex] = lhs[leftIndex];
                leftIndex++;
            } else {
                result[leftIndex + rightIndex] = rhs[rightIndex];
                rightIndex++;
            }
        }

        while (leftIndex < lhs.length) {
            result[leftIndex + rightIndex] = lhs[leftIndex];
            leftIndex++;
        }

        while (rightIndex < rhs.length) {
            result[leftIndex + rightIndex] = rhs[rightIndex];
            rightIndex++;
        }

        return result;
    }

    /**
     * Sorts an array from index <code>startIndex</code> (inclusive) to <code>endIndex</code> (exclusive).
     * @param array
     * @param startIndex
     * @param endIndex
     * @return new array that is sorted
     */
    private static int[] mergeSort(int[] array, int startIndex, int endIndex) throws InterruptedException {
        int length = endIndex - startIndex;
        if (length == 0) {
            return new int[]{};
        }
        if (length == 1) {
            return new int[]{array[startIndex]};
        }

        int halfLength = length / 2;
        int[] sortedLeftPart = mergeSort(array, startIndex, startIndex + halfLength);
        int[] sortedRightPart = mergeSort(array, startIndex + halfLength, endIndex);

        return merge(sortedLeftPart, sortedRightPart);
    }

    /**
     * Sorts a given array (ascending order)
     * @param array
     * @return
     */
    private static int[] sort(int[] array) throws InterruptedException {
        //TODO: use multiple threads to speed up the sorting

        //bestimmt die Anzahl der Prozessoren
        int anzahl = java.lang.Runtime.getRuntime().availableProcessors();
        //Initialisiert die Threads mit der Anzahl der Prozessoren
        Thread[] thread = new Thread[anzahl];
        WorkThread[] w = new WorkThread[anzahl];
        //Teilt die Arrays in Teilarrays auf und startet die Threads
        int faktor = 0;
        int index = 0;
        for (Thread t : thread) {
            w[index] = new WorkThread(split(array, faktor, (array.length / anzahl) - 1));
            t = w[index];
            t.start(); //startet die Threads
            faktor += (array.length / anzahl) - 1;
            index++;
        }

        for (Thread t : thread) {
            t.join(); // hier kommt eine NullpointerException
        }
        for (int i = 0; i < w.length - 1; i++) {
            array = merge(w[i].getArray(), w[i + 1].getArray());
        }
        return array;
    }

    private static int[] split(int[] array, int startIndex, int endIndex) {
        ArrayList<Integer> liste = new ArrayList<Integer>();

        int k = startIndex;
        for (int i = 0; i < endIndex; i++) {
            liste.add(array[k]);
            k++;
        }

        int[] result = new int[liste.size()];
        for (int i = 0; i < liste.size(); i++) {
            result[i] = liste.get(i);
        }
        return result;
    }

    private static class WorkThread extends Thread {

        private int[] array;

        public WorkThread(int[] array) {
            this.array = array;
        }

        @Override
        public synchronized void run() {
            try {
                array = sort();

            } catch (InterruptedException ex) {
            }
        }

        private synchronized int[] sort() throws InterruptedException {
            return mergeSort(array, 0, array.length);
        }

        public synchronized int[] getArray() {
            return array;
        }
    }
}
 

Volvagia

Top Contributor
Du definierst ein Array "thread" und erzeugst es, schreibst aber nichts in die Felder. Deshalb bekommst du für jedes Feld nur null zurückgeliefert.
Nebenbei fliegt mir aber schon ein OutOfMemoryError in der split.

Was hat dich darauf gebracht, 2 Arrays für Thread zu machen, und die Methoden darin zu synchronisieren?
 
Zuletzt bearbeitet:

deppensido

Mitglied
Hallo,

da ich das heute noch fertig kriegen muss:
könntest du vielleicht den Code so umschreiben das
er funktioniert. Ansonsten müsste ich folgende Alternativlösung
nehmen, die wirklich nicht gut ist, aber wenigstens syntaktisch läuft.

Java:
package gp2.ha5.exercise2;

import java.util.ArrayList;
import java.util.Random;
import java.util.logging.Level;
import java.util.logging.Logger;

public class Exercise2 {

    public static Random random = new Random(100);

    public static void main(String[] args) throws InterruptedException {

        int[] array = createRandomArray(10000000);

        long time = System.currentTimeMillis();

        int[] sortedArray = sort(array);

        if (sortedArray.length != array.length || !isSorted(sortedArray)) {
            System.err.println("Failed to sort given array! :-(");
            return;
        }
        System.out.println("Success! Sorting took " + (System.currentTimeMillis() - time) + "ms.");
    }

    /**
     * Creates a randomly filled array of given length
     * @param length
     * @return
     */
    private static int[] createRandomArray(int length) {
        int[] result = new int[length];
        for (int i = 0; i < length; i++) {
            result[i] = random.nextInt();
        }
        return result;
    }

    /**
     * Checks whether a given int array is sorted in ascending order
     * @param array
     * @return <code>true</code> if the given int array is sorted; <code>false</code> otherwise.
     */
    private static boolean isSorted(int[] array) {
        for (int i = 1; i < array.length; i++) {
            if (array[i] < array[i - 1]) {
                return false;
            }
        }
        return true;
    }

    /**
     * Merges two sorted int array into one new sorted array.
     * @param lhs
     * @param rhs
     * @return
     */
    private static int[] merge(int[] lhs, int[] rhs) {
        int[] result = new int[lhs.length + rhs.length];

        int leftIndex = 0;
        int rightIndex = 0;
        while (leftIndex < lhs.length && rightIndex < rhs.length) {
            if (lhs[leftIndex] <= rhs[rightIndex]) {
                result[leftIndex + rightIndex] = lhs[leftIndex];
                leftIndex++;
            } else {
                result[leftIndex + rightIndex] = rhs[rightIndex];
                rightIndex++;
            }
        }

        while (leftIndex < lhs.length) {
            result[leftIndex + rightIndex] = lhs[leftIndex];
            leftIndex++;
        }

        while (rightIndex < rhs.length) {
            result[leftIndex + rightIndex] = rhs[rightIndex];
            rightIndex++;
        }

        return result;
    }

    /**
     * Sorts an array from index <code>startIndex</code> (inclusive) to <code>endIndex</code> (exclusive).
     * @param array
     * @param startIndex
     * @param endIndex
     * @return new array that is sorted
     */
    private static int[] mergeSort(int[] array, int startIndex, int endIndex) throws InterruptedException {
        int length = endIndex - startIndex;
        if (length == 0) {
            return new int[]{};
        }
        if (length == 1) {
            return new int[]{array[startIndex]};
        }

        int halfLength = length / 2;
        int[] sortedLeftPart = mergeSort(array, startIndex, startIndex + halfLength);
        int[] sortedRightPart = mergeSort(array, startIndex + halfLength, endIndex);

        return merge(sortedLeftPart, sortedRightPart);
    }

    /**
     * Sorts a given array (ascending order)
     * @param array
     * @return
     */
    private static int[] sort(int[] array) throws InterruptedException {
        //TODO: use multiple threads to speed up the sorting

        //bestimmt die Anzahl der Prozessoren
        int anzahl = java.lang.Runtime.getRuntime().availableProcessors();
        //Initialisiert die Threads mit der Anzahl der Prozessoren
        Thread[] thread = new Thread[anzahl];
        //Das linke und rechte Teilarray wird initialisiert
        int[] left = splitLeft(array, anzahl);
        int[] right = splitRight(array, anzahl);
        //Die Threads bekommen das linke und rechte Teilarray uebergeben
        thread[0] = new WorkThread(left);
        thread[1] = new WorkThread(right);
        //Threads werden gestartet
        for (Thread t : thread) {
            t.start();
        }
        //wartet auf den ersten Thread
        thread[0].join();
        //Das leftArray bekommt das Ergebnis vom ersten Thread
        left = WorkThread.array;
        //wartet auf den zweiten Thread
        thread[1].join();
        //Das RightArray bekommt das Ergebnis vom zweiten Thread
        right = WorkThread.array;
        //Beide Thread-Ergebnisse werden zusammengefuegt
        return merge(left, right);
    }

    private static int[] splitLeft(int[] array, int anzahl) {
        int[] left = new int[array.length / anzahl];
        for (int i = 0; i < left.length; i++) {
            left[i] = array[i];
        }
        return left;
    }

    private static int[] splitRight(int[] array, int anzahl) {
        int[] right = new int[array.length / anzahl];
        int k = array.length / 2;
        for (int i = 0; i < right.length; i++) {
            right[i] = array[k];
            k++;
        }
        return right;
    }

    private static class WorkThread extends Thread {

        public static int[] array;

        public WorkThread(int[] array) {
            WorkThread.array = array;
        }

        @Override
        public synchronized void run() {
            try {
                array = sort();

            } catch (InterruptedException ex) {
            }
        }

        private synchronized int[] sort() throws InterruptedException {
            return mergeSort(array, 0, array.length);
        }
    }
}
 

Volvagia

Top Contributor
Wenn es funktioniert, dann verwende es doch. Allerdings wirst du hier unter bestimmten Umständen in der sort(int[]) wieder eine NPE bekommen, selber Grund wie oben.
 

deppensido

Mitglied
Der Grund ist halt, dass man nach Aufgabenstellung so viele Threads erzeugen soll,
wie die Java-VM Prozesse zur Verfügung stellt. Bei sind es jedoch immer nur 2 Threads
die benutzt werden. Theoretisch, sollen also z.B. 4 Threads das Sortierproblem
bearbeiten, falls die VM vier Prozessoren zur Verfügung stehen.

Gruß Volker
 

student_nrw

Mitglied
Hi Volker,

den Konstruktor der WorkThread Klasse würde ich noch um die Start- und End-Position der Teilarrays erweitern... diese müsstest du dann quasi in einer for-Schleife errechnen und an den Konstruktor übergeben. Und die Objekte der WorkThread Klasse in eine ArrayList ablegen.

in der run()-Methode rufst du dann mergeSort() auf und hier übergibst du jeweils die beiden Positionen.
das zurückgegebene Array speicherst du bei dem Objekt. So hast du dann x sortierte Arrays und diese kannst du dann mit der merge()-Methode zu einem neuen Array fügen.

Auf diese Weise brauchst du die mergeSort()-Methode nicht mehr ... und schon läuft das Programm schneller :)

Gruß
Eugen
 

deppensido

Mitglied
Hallo Eugen,

hab jetzt dank deiner Hilfe die WorkThread Methode ueberarbeitet,
aber ich weiß nicht, wie ich jetzt die Teilarrays erstellen soll, deshalb hab ich da noch nichts
geändert. Hoffe du kannst mir dabei nochmal helfen. Gruß Volker

Java:
package gp2.ha5.exercise2;

import java.util.ArrayList;
import java.util.Random;

/**
 * Die Klasse erstellt ein zufallsArray
 * und sortiert es mit mergeSort
 * mit Hilfe der Multithreading Technik
 * @author volker
 * @version 1.0
 */
public class Exercise2 {

    public static Random random = new Random(100);

    public static void main(String[] args) throws InterruptedException {

        int[] array = createRandomArray(10000000);

        long time = System.currentTimeMillis();

        int[] sortedArray = sort(array);

        if (sortedArray.length != array.length || !isSorted(sortedArray)) {
            System.err.println("Failed to sort given array! :-(");
            return;
        }
        System.out.println("Success! Sorting took " + (System.currentTimeMillis() - time) + "ms.");
    }

    /**
     * Creates a randomly filled array of given length
     * @param length
     * @return
     */
    private static int[] createRandomArray(int length) {
        int[] result = new int[length];
        for (int i = 0; i < length; i++) {
            result[i] = random.nextInt();
        }
        return result;
    }

    /**
     * Checks whether a given int array is sorted in ascending order
     * @param array
     * @return <code>true</code> if the given int array is sorted; <code>false</code> otherwise.
     */
    private static boolean isSorted(int[] array) {
        for (int i = 1; i < array.length; i++) {
            if (array[i] < array[i - 1]) {
                return false;
            }
        }
        return true;
    }

    /**
     * Merges two sorted int array into one new sorted array.
     * @param lhs
     * @param rhs
     * @return
     */
    private static int[] merge(int[] lhs, int[] rhs) {
        int[] result = new int[lhs.length + rhs.length];

        int leftIndex = 0;
        int rightIndex = 0;
        while (leftIndex < lhs.length && rightIndex < rhs.length) {
            if (lhs[leftIndex] <= rhs[rightIndex]) {
                result[leftIndex + rightIndex] = lhs[leftIndex];
                leftIndex++;
            } else {
                result[leftIndex + rightIndex] = rhs[rightIndex];
                rightIndex++;
            }
        }

        while (leftIndex < lhs.length) {
            result[leftIndex + rightIndex] = lhs[leftIndex];
            leftIndex++;
        }

        while (rightIndex < rhs.length) {
            result[leftIndex + rightIndex] = rhs[rightIndex];
            rightIndex++;
        }

        return result;
    }

    /**
     * Sorts an array from index <code>startIndex</code> (inclusive) to <code>endIndex</code> (exclusive).
     * @param array
     * @param startIndex
     * @param endIndex
     * @return new array that is sorted
     */
    private static int[] mergeSort(int[] array, int startIndex, int endIndex) throws InterruptedException {
        int length = endIndex - startIndex;
        if (length == 0) {
            return new int[]{};
        }
        if (length == 1) {
            return new int[]{array[startIndex]};
        }

        int halfLength = length / 2;
        int[] sortedLeftPart = mergeSort(array, startIndex, startIndex + halfLength);
        int[] sortedRightPart = mergeSort(array, startIndex + halfLength, endIndex);

        return merge(sortedLeftPart, sortedRightPart);
    }

    /**
     * Sorts a given array (ascending order)
     * @param array
     * @return
     */
    private static int[] sort(int[] array) throws InterruptedException {
        //TODO: use multiple threads to speed up the sorting

        //bestimmt die Anzahl der Prozessoren
        int anzahl = java.lang.Runtime.getRuntime().availableProcessors();
        //Initialisiert die Threads mit der Anzahl der Prozessoren
        Thread[] thread = new Thread[anzahl];
        //Das linke und rechte Teilarray wird initialisiert
        int[] left = splitLeft(array);
        int[] right = splitRight(array);
        //Die Threads bekommen das linke und rechte Teilarray uebergeben
        thread[0] = new WorkThread(left, 0, left.length);
        thread[1] = new WorkThread(right, array.length / 2, right.length);
        //Threads werden gestartet
        for (Thread t : thread) {
            t.start();
        }
        //wartet auf den ersten Thread
        thread[0].join();
        //Das leftArray bekommt das Ergebnis vom ersten Thread
        left = WorkThread.array;
        //wartet auf den zweiten Thread
        thread[1].join();
        //Das RightArray bekommt das Ergebnis vom zweiten Thread
        right = WorkThread.array;
        //Beide Thread-Ergebnisse werden zusammengefuegt
        return merge(left, right);
    }

    /**
     *
     * teilt das Array und gibt das linke Teilarray zurueck
     * @param array
     * @param anzahl
     * @return
     */
    private static int[] splitLeft(int[] array) {
        int[] left = new int[array.length / 2];
        for (int i = 0; i < left.length; i++) {
            left[i] = array[i];
        }
        return left;
    }

    /**
     * teilt das Array und gibt das rechte Teilarray zurueck
     * @param array
     * @param anzahl
     * @return
     */
    private static int[] splitRight(int[] array) {
        int[] right = new int[array.length / 2];
        int k = array.length / 2;
        for (int i = 0; i < right.length; i++) {
            right[i] = array[k];
            k++;
        }
        return right;
    }

    /** 
     * Die Klasse sortiert ein uebergebendes Teilarray
     * per mergeSort
     */
    private static class WorkThread extends Thread {

        /**Array auf das zugegriffen werden soll*/
        public static int[] array;
        /**Arrayliste in der die Teilarrays gespeichert werden*/
        public ArrayList<int[]> list = new ArrayList<int[]>();
        /**Start und Endposition der Teilarrays */
        int startPos, endPos;

        /**
         * Konstruktor weist das Teilarray zu
         * @param array
         */
        public WorkThread(int[] array, int startPos, int endPos) {
            WorkThread.array = array;
            this.startPos = startPos;
            this.endPos = endPos;
        }

        /**
         * Weist dem array das Sortierergebnis zu
         */
        @Override
        public void run() {
            try {
                array = sort(this.startPos, this.endPos);
                list.add(array);
                for (int i = 0; i < list.size() - 1; i++) {
                    array = merge(list.get(i), list.get(i + 1));
                }

            } catch (InterruptedException ex) {
            }
        }

        /**
         * sortiert das Teilarray
         * @return
         * @throws InterruptedException
         */
        private int[] sort(int s, int e) throws InterruptedException {
            return mergeSort(array, s, e);
        }
    }
}
 

student_nrw

Mitglied
die ArrayList<int[]> list ist überflüssig ... mach die weg dann ist die WorkThread-Klasse so okay

die sort-methode müsste in etwa so sein...

Java:
private static int[] sort(int[] array) throws InterruptedException {
int anzahl = java.lang.Runtime.getRuntime().availableProcessors();
Thread[] thread = new Thread[anzahl];
       
for(int i=0; i<anzahl;i++{

thread[i] = new WorkThread();

}

int startPos;
int endPos;

for (Thread t : thread) {

//nun musst du einen kleinen alogorithmus schreiben wie man auf die start- und endPos kommt
//also wenn dein array z.B. aus 10 zahlen besteht und anzahl der prozesse = 2 ist
//dann hätten wir im ersten durchlauf 0 und 5, im zweiten 5 und 10
//im arrayfeld wären das ja 0 und 4, 5 und 9

startPos=???
endPos=???

t.start(array,startPos,endPos);
}

//warten bis alle fertig sind
for (Thread t : thread) {
t.join();
}


//und nun musst du durch dein thread-array durchgehen und zum array von t1 das aus t2 addieren
//dann zu diesem zusammengesetzten array noch das von t3 usw ... auf diese weise wächst dann
//dein array


//in etwa so
int [] dein_neues_array = new int [0];
for (Thread t : thread) {
dein_neues_array=merge(dein_neues_array,t.getArray());
}
//ja die getArray()-Methode bräuchtest du dann auch noch
//dein_neues_array wäre dann am ende das vollständig sortierte array

return dein_neues_array;
}

Guck mal wie weit du damit kommst ... ich komme später noch mal online
 

deppensido

Mitglied
mir ist gerade aufgefallen, dass t.start() keine Parameter
bekommen kann, zum anderen kommt bei t.start() eine NullPointerException

Gruß Volker
 

deppensido

Mitglied
hallo,
nun sieht meine sort methode so aus.
Wie im Code kommentiert klappt scheinbar das array teilen nicht.
Gruß Volker
Java:
private static int[] sort(int[] array) throws InterruptedException {
        int anzahl = java.lang.Runtime.getRuntime().availableProcessors();
        Thread[] thread = new Thread[anzahl];

        int startPos;
        int endPos = 0;
        int k = 0;
        //Hier muss was falsch sein
        for (int i = 0; i < thread.length; i++) {
            startPos = k;
            endPos += array.length / anzahl;
            thread[i] = new WorkThread(array, startPos, endPos);
            k += endPos/anzahl;
        }

        for (Thread t : thread) {
            t.start();
        }
        //warten bis alle fertig sind
        for (Thread t : thread) {
            t.join();
        }

        int[] result = new int[0];

        result = merge(result, WorkThread.array);


        return result;
    }
 

student_nrw

Mitglied
ops... tut mir leid du hast natürlich recht!!!

Java:
private static int[] sort(int[] array) throws InterruptedException {
int anzahl = java.lang.Runtime.getRuntime().availableProcessors();
Thread[] thread = new Thread[anzahl];
       
int startPos;
int endPos;

for(int i=0; i<anzahl;i++{

startPos=???
endPos=???
 
thread[i] = new WorkThread(array,startPos,endPos);
thread[i].start(); //müsste hier denk ich so gehen
}
 
//sonst so
for (Thread t : thread) {
t.start();
}
...
...
 

student_nrw

Mitglied
okay ... du warst schneller

ops... tut mir leid du hast natürlich recht!!!

Java:
private static int[] sort(int[] array) throws InterruptedException {
int anzahl = java.lang.Runtime.getRuntime().availableProcessors();
Thread[] thread = new Thread[anzahl];
       
int startPos;
int endPos;

for(int i=0; i<anzahl;i++{

startPos=???
endPos=???
 
thread[i] = new WorkThread(array,startPos,endPos);
thread[i].start(); //müsste hier denk ich so gehen
}
 
//sonst so
for (Thread t : thread) {
t.start();
}
...
...
 

student_nrw

Mitglied
ja da war ein rechenfehler, probiere das mal so.

Java:
for (int i = 0; i < thread.length; i++) {
            startPos = k;
            endPos += array.length / anzahl;
            thread[i] = new TeilArray(array, startPos, endPos);
            k = endPos;
        }
 

student_nrw

Mitglied
zum Schluss brauchst du glaub ich das hier:

Java:
int[] result = new int[0];
for (Thread t : thread) {
result = merge(result, t.array);
}
 

deppensido

Mitglied
Hallo,

es funktioniert jetzt endlich.:)
Vielen Dank für deine Hilfe.
Hier nochmal die gesamte Lösung,
falls jemand mal interesse für sowas hat.

Gruß Volker

Java:
package gp2.ha5.exercise2;

import java.util.ArrayList;
import java.util.Random;
import sun.audio.AudioPlayer;

/**
 * Die Klasse erstellt ein zufallsArray
 * und sortiert es mit mergeSort
 * mit Hilfe der Multithreading Technik
 * @author volker
 * @version 1.0
 */
public class Exercise2 {

    public static Random random = new Random(100);

    public static void main(String[] args) throws InterruptedException {

        int[] array = createRandomArray(10000000);

        long time = System.currentTimeMillis();

        int[] sortedArray = sort(array);

        if (sortedArray.length != array.length || !isSorted(sortedArray)) {
            System.err.println("Failed to sort given array! :-(");
            return;
        }
        System.out.println("Success! Sorting took " + (System.currentTimeMillis() - time) + "ms.");
    }

    /**
     * Creates a randomly filled array of given length
     * @param length
     * @return
     */
    private static int[] createRandomArray(int length) {
        int[] result = new int[length];
        for (int i = 0; i < length; i++) {
            result[i] = random.nextInt();
        }
        return result;
    }

    /**
     * Checks whether a given int array is sorted in ascending order
     * @param array
     * @return <code>true</code> if the given int array is sorted; <code>false</code> otherwise.
     */
    private static boolean isSorted(int[] array) {
        for (int i = 1; i < array.length; i++) {
            if (array[i] < array[i - 1]) {
                return false;
            }
        }
        return true;
    }

    /**
     * Merges two sorted int array into one new sorted array.
     * @param lhs
     * @param rhs
     * @return
     */
    private static int[] merge(int[] lhs, int[] rhs) {
        int[] result = new int[lhs.length + rhs.length];

        int leftIndex = 0;
        int rightIndex = 0;
        while (leftIndex < lhs.length && rightIndex < rhs.length) {
            if (lhs[leftIndex] <= rhs[rightIndex]) {
                result[leftIndex + rightIndex] = lhs[leftIndex];
                leftIndex++;
            } else {
                result[leftIndex + rightIndex] = rhs[rightIndex];
                rightIndex++;
            }
        }

        while (leftIndex < lhs.length) {
            result[leftIndex + rightIndex] = lhs[leftIndex];
            leftIndex++;
        }

        while (rightIndex < rhs.length) {
            result[leftIndex + rightIndex] = rhs[rightIndex];
            rightIndex++;
        }

        return result;
    }

    /**
     * Sorts an array from index <code>startIndex</code> (inclusive) to <code>endIndex</code> (exclusive).
     * @param array
     * @param startIndex
     * @param endIndex
     * @return new array that is sorted
     */
    private static int[] mergeSort(int[] array, int startIndex, int endIndex) throws InterruptedException {
        int length = endIndex - startIndex;
        if (length == 0) {
            return new int[]{};
        }
        if (length == 1) {
            return new int[]{array[startIndex]};
        }

        int halfLength = length / 2;
        int[] sortedLeftPart = mergeSort(array, startIndex, startIndex + halfLength);
        int[] sortedRightPart = mergeSort(array, startIndex + halfLength, endIndex);

        return merge(sortedLeftPart, sortedRightPart);
    }

    /**
     * Sorts a given array (ascending order)
     * @param array
     * @return
     */
    /*
    private static int[] sort(int[] array) throws InterruptedException {
    //TODO: use multiple threads to speed up the sorting
    
    //bestimmt die Anzahl der Prozessoren
    int anzahl = java.lang.Runtime.getRuntime().availableProcessors();
    //Initialisiert die Threads mit der Anzahl der Prozessoren
    Thread[] thread = new Thread[anzahl];
    //Das linke und rechte Teilarray wird initialisiert
    int[] left = splitLeft(array);
    int[] right = splitRight(array);
    //Die Threads bekommen das linke und rechte Teilarray uebergeben
    thread[0] = new WorkThread(left, 0, left.length);
    thread[1] = new WorkThread(right, array.length / 2, right.length);
    //Threads werden gestartet
    for (Thread t : thread) {
    t.start();
    }
    //wartet auf den ersten Thread
    thread[0].join();
    //Das leftArray bekommt das Ergebnis vom ersten Thread
    left = WorkThread.array;
    
    //wartet auf den zweiten Thread
    thread[1].join();
    //Das RightArray bekommt das Ergebnis vom zweiten Thread
    right = WorkThread.array;
    
    //Beide Thread-Ergebnisse werden zusammengefuegt
    return merge(left, right);
    }
     */
    private static int[] sort(int[] array) throws InterruptedException {
        int anzahl = java.lang.Runtime.getRuntime().availableProcessors();
        Thread[] thread = new Thread[anzahl];

        int startPos;
        int endPos = 0;
        int k = 0;
        //Hier muss was falsch sein
        for (int i = 0; i < thread.length; i++) {
            startPos = k;
            endPos += array.length / anzahl;
            thread[i] = new WorkThread(array, startPos, endPos);
            k = endPos;
        }

        for (Thread t : thread) {
            t.start();
        }
        //warten bis alle fertig sind
        for (Thread t : thread) {
            t.join();
        }

        int[] result = new int[0];
        for (Thread t : thread) {
            result = merge(result, WorkThread.array);
        }

        return result;
    }

    /**
     *
     * teilt das Array und gibt das linke Teilarray zurueck
     * @param array
     * @param anzahl
     * @return
     */
    private static int[] splitLeft(int[] array) {
        int[] left = new int[array.length / 2];
        for (int i = 0; i < left.length; i++) {
            left[i] = array[i];
        }
        return left;
    }

    /**
     * teilt das Array und gibt das rechte Teilarray zurueck
     * @param array
     * @param anzahl
     * @return
     */
    private static int[] splitRight(int[] array) {
        int[] right = new int[array.length / 2];
        int k = array.length / 2;
        for (int i = 0; i < right.length; i++) {
            right[i] = array[k];
            k++;
        }
        return right;
    }

    /**
     * Die Klasse sortiert ein uebergebendes Teilarray
     * per mergeSort
     */
    private static class WorkThread extends Thread {

        /**Array auf das zugegriffen werden soll*/
        public static int[] array;
        /**Start und Endposition der Teilarrays */
        private int startPos, endPos;

        /**
         * Konstruktor weist das Teilarray zu
         * @param array
         */
        public WorkThread(int[] array, int startPos, int endPos) {
            WorkThread.array = array;
            this.startPos = startPos;
            this.endPos = endPos;
        }

        /**
         * Weist dem array das Sortierergebnis zu
         */
        @Override
        public void run() {
            try {
                array = sort(this.startPos, this.endPos);
            } catch (InterruptedException ex) {
                System.out.println("fehler");
            }
        }

        /**
         * sortiert das Teilarray
         * @return
         * @throws InterruptedException
         */
        private synchronized int[] sort(int s, int e) throws InterruptedException {
            return mergeSort(array, s, e);
        }
    }
}
 
Zuletzt bearbeitet:

student_nrw

Mitglied
Bitte schön ;-)

Ich hätte nur den Code nach der Abgabe hier postiert... sonst wird man dir noch eine Plagiat-Lösung vorwerfen... falls jemand deinen Quellcode 1:1 übernimmt ;-)
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
W Multithreading Alphabet Allgemeine Java-Themen 3
T Multithreading: Wie viele Threads sollte ich erstellen? Allgemeine Java-Themen 12
J Threads Multithreading Allgemeine Java-Themen 15
K Multithreading plattform übergreifend? Allgemeine Java-Themen 3
R Bruteforce hashes mit multithreading. Funktioniert das so? Allgemeine Java-Themen 0
B Threads Multithreading Threads sollen warten Allgemeine Java-Themen 12
K Multithreading: Service(Task), wait und continue Allgemeine Java-Themen 21
M JUnit & Multithreading - sehr seltener Fehler Allgemeine Java-Themen 3
C Ressourcensparendes Multithreading Allgemeine Java-Themen 3
A Multithreading mit JButtons Allgemeine Java-Themen 5
S Threads Multithreading- langsamer als Singlethreading-Programm Allgemeine Java-Themen 6
A MultiThreading.. Scheduling-Problem? Allgemeine Java-Themen 10
M Multithreading Problem Allgemeine Java-Themen 3
dayaftereh Multithreading Allgemeine Java-Themen 16
E Multithreading and volatile Allgemeine Java-Themen 10
J Wie die gleichzeitige Ausführung mehrerer Tasks trotz Multithreading verhindern? Allgemeine Java-Themen 2
G multithreading, concurrency conveyor belt beispiel Allgemeine Java-Themen 2
A Problem mit Zufallszahlen und Multithreading Allgemeine Java-Themen 14
I Problem mit Multithreading Allgemeine Java-Themen 4
H Singleton und MultiThreading [erledigt] Allgemeine Java-Themen 3
C Collection Multithreading? Allgemeine Java-Themen 33
O Multithreading mit Java 5 u den Concurrency APIs Allgemeine Java-Themen 7
O Multithreading und Multiprozessor Allgemeine Java-Themen 4
K Multithreading bei statischen Methoden Allgemeine Java-Themen 2
T ungewöhnliche Exception (Multithreading und JList) Allgemeine Java-Themen 10
K Frage zu ProgressBars, Algorithmen und Multithreading ->F Allgemeine Java-Themen 2
flashfactor Multithreading-Problem Allgemeine Java-Themen 4

Ähnliche Java Themen

Neue Themen


Oben