Enfreyer
- Forum-Beiträge: 9
29.03.2013, 17:56:30 via Website
29.03.2013 17:56:30 via Website
Hallo Leute,
ich entwickle gerade ein Benchmarkprogramm, welches eine frei wählbare Anzahl an
Primzahlen auf einer beliebigen Anzahl an Threads berechnet.
Erst habe ich es mit AsyncTasks versucht, bei der anschließenden Überwachung
der CPU aber festgestellt, ein AsyncTask nicht auf einen freien CPU Thread
ausgelagert wird und somit keine Mehrleistung entsteht.
Nun arbeite ich mit Threads; die Parallelisierung funktioniert fast perfekt.
Prinzip:
Es gibt genau einen Handler in Mainthread. Beim Start des Benchmarkes wird
aus einem Editfeld gelesen, wie viele Threads erzeugt werden sollen. Erzeuge
ich zb 4 Threads, bekommt jeder dieser Threads den gleichen Handler übergeben.
Es gibt nur ein Problem:
Der Handler im Mainthread, der für die Überwachung aller Threads verantwortlich ist,
die Berechnungen für den Benchmark vornehmen, empfängt die Messages der Threads
total durcheinander und Zeitversetzt. Außerdem kommt oft derselbe Wert auch
mehrmals hintereinander an, obwohl er in den Threads definitiv nur einmal auftaucht.
Wenn ich die Ausgaben der Threads im Innern protokolliere, stimmt die Reihenfolge
ebenfalls.
MainClass:
PrimzahlThread
Es sind keine Warnungen mehr im Code, alles sauber. Hat jemand eine Ahnung, warum die
Messages der Threads nicht rechtzeitig ankommen?
ich entwickle gerade ein Benchmarkprogramm, welches eine frei wählbare Anzahl an
Primzahlen auf einer beliebigen Anzahl an Threads berechnet.
Erst habe ich es mit AsyncTasks versucht, bei der anschließenden Überwachung
der CPU aber festgestellt, ein AsyncTask nicht auf einen freien CPU Thread
ausgelagert wird und somit keine Mehrleistung entsteht.
Nun arbeite ich mit Threads; die Parallelisierung funktioniert fast perfekt.
Prinzip:
Es gibt genau einen Handler in Mainthread. Beim Start des Benchmarkes wird
aus einem Editfeld gelesen, wie viele Threads erzeugt werden sollen. Erzeuge
ich zb 4 Threads, bekommt jeder dieser Threads den gleichen Handler übergeben.
Es gibt nur ein Problem:
Der Handler im Mainthread, der für die Überwachung aller Threads verantwortlich ist,
die Berechnungen für den Benchmark vornehmen, empfängt die Messages der Threads
total durcheinander und Zeitversetzt. Außerdem kommt oft derselbe Wert auch
mehrmals hintereinander an, obwohl er in den Threads definitiv nur einmal auftaucht.
Wenn ich die Ausgaben der Threads im Innern protokolliere, stimmt die Reihenfolge
ebenfalls.
MainClass:
1public class MainActivity extends Activity {
2 static TextView timeView;
3 static long beforeTime = 0;
4 static long afterTime = 0;
5 static List<Integer> result = new ArrayList<Integer>();
6 static List<PrimeThread> threadList = new ArrayList<PrimeThread>();
7 static int threadCount;
8 static int primeCount;
9 static int primesFound;
10
11 final static Handler handler = new Handler() {
12 public void handleMessage(Message msg) {
13 //Nimm nur weitere Ergebnisse der Threads entgegen, solange Ziel (primesFound) noch nicht erreicht
14 if (primesFound <= primeCount) {
15 primesFound ++;
16
17 //wenn primesFound erreicht, stoppe die Zeit und die Threads
18 if (primesFound >= primeCount) {
19 afterTime = System.currentTimeMillis();
20 long resultTime = afterTime - beforeTime;
21 System.out.println(resultTime);
22 timeView.setText(String.valueOf(resultTime));
23 stopThreads(threadList);
24
25 }
26 }
27 }
28 };
29
30 //Entnimmt der Oberfläche die Eingabewerte threadCount und primeCount
31 public void startCalculation(View view) {
32 primesFound = 0; //counter der gefunden Primzahlen für den Handler
33 EditText primeEdit = (EditText) findViewById(R.id.primeIn);
34 EditText threadEdit = (EditText) findViewById(R.id.threadIn);
35 timeView = (TextView) findViewById(R.id.timeOut);
36
37 primeCount = Integer.parseInt(primeEdit.getText().toString());
38 threadCount = Integer.parseInt(threadEdit.getText().toString());
39
40 threadList = getThreadList(threadCount);
41 beforeTime = System.currentTimeMillis();
42 startThreads(threadList);
43 }
44
45
46 private void startThreads(List<PrimeThread> threads) {
47 for (int i = 0; i < threadCount; i++) {
48 threads.get(i).start();
49 }
50 }
51
52 private static void stopThreads(List<PrimeThread> threads) {
53 for (int i = 0; i < threadCount; i++) {
54 threads.get(i).terminated = true;
55 }
56 }
57
58 //erzeugt i (i = threadCount) threads und gibt jedem den Handler mit
59 private List<PrimeThread> getThreadList(int threadCount) {
60 List<PrimeThread> result = new ArrayList<PrimeThread>();
61 for (int i = 0; i < threadCount; i++) {
62 PrimeThread pt = new PrimeThread(i, threadCount, handler);
63 result.add(pt);
64 }
65 return result;
66 }
67}
2 static TextView timeView;
3 static long beforeTime = 0;
4 static long afterTime = 0;
5 static List<Integer> result = new ArrayList<Integer>();
6 static List<PrimeThread> threadList = new ArrayList<PrimeThread>();
7 static int threadCount;
8 static int primeCount;
9 static int primesFound;
10
11 final static Handler handler = new Handler() {
12 public void handleMessage(Message msg) {
13 //Nimm nur weitere Ergebnisse der Threads entgegen, solange Ziel (primesFound) noch nicht erreicht
14 if (primesFound <= primeCount) {
15 primesFound ++;
16
17 //wenn primesFound erreicht, stoppe die Zeit und die Threads
18 if (primesFound >= primeCount) {
19 afterTime = System.currentTimeMillis();
20 long resultTime = afterTime - beforeTime;
21 System.out.println(resultTime);
22 timeView.setText(String.valueOf(resultTime));
23 stopThreads(threadList);
24
25 }
26 }
27 }
28 };
29
30 //Entnimmt der Oberfläche die Eingabewerte threadCount und primeCount
31 public void startCalculation(View view) {
32 primesFound = 0; //counter der gefunden Primzahlen für den Handler
33 EditText primeEdit = (EditText) findViewById(R.id.primeIn);
34 EditText threadEdit = (EditText) findViewById(R.id.threadIn);
35 timeView = (TextView) findViewById(R.id.timeOut);
36
37 primeCount = Integer.parseInt(primeEdit.getText().toString());
38 threadCount = Integer.parseInt(threadEdit.getText().toString());
39
40 threadList = getThreadList(threadCount);
41 beforeTime = System.currentTimeMillis();
42 startThreads(threadList);
43 }
44
45
46 private void startThreads(List<PrimeThread> threads) {
47 for (int i = 0; i < threadCount; i++) {
48 threads.get(i).start();
49 }
50 }
51
52 private static void stopThreads(List<PrimeThread> threads) {
53 for (int i = 0; i < threadCount; i++) {
54 threads.get(i).terminated = true;
55 }
56 }
57
58 //erzeugt i (i = threadCount) threads und gibt jedem den Handler mit
59 private List<PrimeThread> getThreadList(int threadCount) {
60 List<PrimeThread> result = new ArrayList<PrimeThread>();
61 for (int i = 0; i < threadCount; i++) {
62 PrimeThread pt = new PrimeThread(i, threadCount, handler);
63 result.add(pt);
64 }
65 return result;
66 }
67}
PrimzahlThread
1public class PrimeThread extends Thread {
2 Handler handler;
3 int threadNumber;
4 int threadCount;
5 boolean terminated = false;
6 ....
7
8 PrimeThread(int a, int b, Handler c) {
9 threadNumber = a;
10 threadCount = b;
11 handler = c;
12 }
13
14 @Override
15 public void run() {
16 ....
17 Bundle b = new Bundle();
18
19 while (!terminated) {
20 currentNumber = getEveryXNumber(currentNumber);
21 if (isPrime(currentNumber)){
22 b.clear();
23 b.putInt("value", currentNumber);
24 sendBundleToMainThread(b);
25 }
26 }
27 }
28
29 private void sendBundleToMainThread(Bundle b) {
30 Message msgObj = handler.obtainMessage();
31 msgObj.setData(b);
32 handler.sendMessage(msgObj);
33 }
34
35 private int getEveryXNumber(int cn){
36 ....
37 }
38
39 boolean isPrime(long n) {
40 ....
41 }
42}
2 Handler handler;
3 int threadNumber;
4 int threadCount;
5 boolean terminated = false;
6 ....
7
8 PrimeThread(int a, int b, Handler c) {
9 threadNumber = a;
10 threadCount = b;
11 handler = c;
12 }
13
14 @Override
15 public void run() {
16 ....
17 Bundle b = new Bundle();
18
19 while (!terminated) {
20 currentNumber = getEveryXNumber(currentNumber);
21 if (isPrime(currentNumber)){
22 b.clear();
23 b.putInt("value", currentNumber);
24 sendBundleToMainThread(b);
25 }
26 }
27 }
28
29 private void sendBundleToMainThread(Bundle b) {
30 Message msgObj = handler.obtainMessage();
31 msgObj.setData(b);
32 handler.sendMessage(msgObj);
33 }
34
35 private int getEveryXNumber(int cn){
36 ....
37 }
38
39 boolean isPrime(long n) {
40 ....
41 }
42}
Es sind keine Warnungen mehr im Code, alles sauber. Hat jemand eine Ahnung, warum die
Messages der Threads nicht rechtzeitig ankommen?
— geändert am 01.04.2013, 13:01:07
Empfohlener redaktioneller Inhalt
Mit Deiner Zustimmung wird hier ein externer Inhalt geladen.
Mit Klick auf den oben stehenden Button erklärst Du Dich damit einverstanden, dass Dir externe Inhalte angezeigt werden dürfen. Dabei können personenbezogene Daten an Drittanbieter übermittelt werden. Mehr Infos dazu findest Du in unserer Datenschutzerklärung.