Derselbe Handler für mehrere dynamisch erzeugte Threads

  • Antworten:1
Enfreyer
  • Forum-Beiträge: 9

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:
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}

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}

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

Antworten
Enfreyer
  • Forum-Beiträge: 9

01.04.2013, 12:58:56 via Website

Das Problem habe ich jetzt mit einer statischen Zählvariable in den
Threads umgangen. Die Ursache dafür, warum ein Handler damit so
überfordert scheint, habe ich aber immer noch nicht verstanden.

— geändert am 01.04.2013, 12:59:20

Antworten