Threads

In folgendem Programm werden n Threads gestartet, die unabhängig voneinander die Zahlen 1 bis 1000 ausgeben

Java:

    private final static int NUMBER = 3;

    public static void main(String[] args) {
        NumberRunner[] runner = new NumberRunner[NUMBER];
        for (int i = 0; i < NUMBER; i++) {
            runner[i] = new NumberRunner(i);
        }
        for (int i = 0; i < NUMBER; i++) {
            runner[i].start();
        }
    }

}
class NumberRunner extends Thread {

    private int number;

    public NumberRunner(int n) {
        number = n;
    }

    @Override
    public void run() {
        for (int i = 0; i < 1000; i++) {
            System.out.println("Thread " + number + ": " + i);
        }
    }
}

Ich wollte in das Programm Thread-Mechanismen einbauen, so dass die Threads nach jeweils 10 Ausgaben auf die anderen warten (Barrier), bevor sie
dann weitermachen.

Mein Quellcode sieht so aus, aber irgendwas läuft schief.

könnte jemand mir helfen ?

vielen Dank im Voraus.

Java:

public class NumberRunner extends Thread {
    private int number;
    private static int count = 0;
    private static int next = 0;
    private static Object obj = new Object();
    private static Semaphore sem = new Semaphore(1);

    public NumberRunner() {
        number = count++;
    }

    @Override
    public void run() {
while(true) {
for (int i = 0; i < 1000; i++) {
            synchronized(obj) {
            
    if(number == next) {   
                    for(int k = 0; k < 10; k++) {
                    System.out.println(getName() + ": " + i);
                    
                }
                try {
                    sleep(50);
                }catch(InterruptedException e) {
                    
                }
                next = (next + 1) % 3;
                obj.notifyAll();
            }else {
                try {
                    obj.wait();
                } catch (InterruptedException e) {   
                }
            }
        }
                
                    
    }
    }
    }
}

Ich denke, du suchst Folgendes:
Java-Code

Es gibt 3 Threads. Sobald ein Thread 0,10,20,30,usw. erreicht hat, wartet er eine bestimmte Zeit (etwa 2 Seknunden), bis auch die anderen 2 Threads 0,10,20,30,usw. erreicht haben. Dadurch zählt kein Thread weiter, wenn noch nicht alle anderen 0,10,20,30,usw. erreicht haben.

Ich bin mir nur gerade etwas unsicher, ob das Verhalten nur am Thread.sleep((m + number / 10 * 2000) % 2000); liegt… und nicht an dem Semaphore. Ich würde mich freuen, wenn sich das noch mal jemand ansieht.

Perfekt, so geht’s: (hatte erst falsch gedacht…)

public class NumberRunner extends Thread {

	private static final int numberOfThreads = 4;

	private static volatile int number2 = 0;
	private int number1 = 1;

	@Override
	public void run() {
		try {
			while (number1 <= 100) {
				System.out.println(this.toString() + " " + number1);
				if (number1 % 10 == 0) {
					number2++;
					while (number2 < number1 / 10 * numberOfThreads) {
						Thread.sleep(1);
					}
				} else {
					Thread.sleep(1);
				}
				number1++;
			}
		} catch (InterruptedException ignore) {
		}
	}

	public static void main(String[] args) {
		for (int i = 0; i < numberOfThreads; i++) {
			new NumberRunner().start();
		}
	}

}
Zusammenfassung

Thread[Thread-1,5,main] 1
Thread[Thread-3,5,main] 1
Thread[Thread-0,5,main] 1
Thread[Thread-2,5,main] 1
Thread[Thread-1,5,main] 2
Thread[Thread-3,5,main] 2
Thread[Thread-0,5,main] 2
Thread[Thread-2,5,main] 2
Thread[Thread-2,5,main] 3
Thread[Thread-1,5,main] 3
Thread[Thread-0,5,main] 3
Thread[Thread-3,5,main] 3
Thread[Thread-1,5,main] 4
Thread[Thread-3,5,main] 4
Thread[Thread-2,5,main] 4
Thread[Thread-0,5,main] 4
Thread[Thread-3,5,main] 5
Thread[Thread-0,5,main] 5
Thread[Thread-2,5,main] 5
Thread[Thread-1,5,main] 5
Thread[Thread-3,5,main] 6
Thread[Thread-0,5,main] 6
Thread[Thread-2,5,main] 6
Thread[Thread-1,5,main] 6
Thread[Thread-0,5,main] 7
Thread[Thread-3,5,main] 7
Thread[Thread-2,5,main] 7
Thread[Thread-1,5,main] 7
Thread[Thread-0,5,main] 8
Thread[Thread-2,5,main] 8
Thread[Thread-3,5,main] 8
Thread[Thread-1,5,main] 8
Thread[Thread-3,5,main] 9
Thread[Thread-1,5,main] 9
Thread[Thread-0,5,main] 9
Thread[Thread-2,5,main] 9
Thread[Thread-1,5,main] 10
Thread[Thread-3,5,main] 10
Thread[Thread-0,5,main] 10
Thread[Thread-2,5,main] 10
Thread[Thread-2,5,main] 11
Thread[Thread-3,5,main] 11
Thread[Thread-1,5,main] 11
Thread[Thread-2,5,main] 12
Thread[Thread-0,5,main] 11
Thread[Thread-1,5,main] 12
Thread[Thread-0,5,main] 12
Thread[Thread-3,5,main] 12
Thread[Thread-2,5,main] 13
Thread[Thread-0,5,main] 13
Thread[Thread-1,5,main] 13
Thread[Thread-3,5,main] 13
Thread[Thread-2,5,main] 14
Thread[Thread-1,5,main] 14
Thread[Thread-2,5,main] 15
Thread[Thread-0,5,main] 14
Thread[Thread-3,5,main] 14
Thread[Thread-2,5,main] 16
Thread[Thread-1,5,main] 15
Thread[Thread-0,5,main] 15
Thread[Thread-3,5,main] 15
Thread[Thread-1,5,main] 16
Thread[Thread-3,5,main] 16
Thread[Thread-0,5,main] 16
Thread[Thread-2,5,main] 17
Thread[Thread-0,5,main] 17
Thread[Thread-1,5,main] 17
Thread[Thread-3,5,main] 17
Thread[Thread-2,5,main] 18
Thread[Thread-0,5,main] 18
Thread[Thread-2,5,main] 19
Thread[Thread-1,5,main] 18
Thread[Thread-3,5,main] 18
Thread[Thread-2,5,main] 20
Thread[Thread-3,5,main] 19
Thread[Thread-0,5,main] 19
Thread[Thread-1,5,main] 19
Thread[Thread-1,5,main] 20
Thread[Thread-0,5,main] 20
Thread[Thread-3,5,main] 20
Thread[Thread-3,5,main] 21
Thread[Thread-2,5,main] 21
Thread[Thread-0,5,main] 21
Thread[Thread-3,5,main] 22
Thread[Thread-1,5,main] 21
Thread[Thread-3,5,main] 23
Thread[Thread-1,5,main] 22
Thread[Thread-0,5,main] 22
Thread[Thread-2,5,main] 22
Thread[Thread-3,5,main] 24
Thread[Thread-2,5,main] 23
Thread[Thread-1,5,main] 23
Thread[Thread-0,5,main] 23
Thread[Thread-3,5,main] 25
Thread[Thread-0,5,main] 24
Thread[Thread-1,5,main] 24
Thread[Thread-2,5,main] 24
Thread[Thread-1,5,main] 25
Thread[Thread-2,5,main] 25
Thread[Thread-0,5,main] 25
Thread[Thread-3,5,main] 26
Thread[Thread-1,5,main] 26
Thread[Thread-3,5,main] 27
Thread[Thread-0,5,main] 26
Thread[Thread-2,5,main] 26
Thread[Thread-1,5,main] 27
Thread[Thread-2,5,main] 27
Thread[Thread-0,5,main] 27
Thread[Thread-3,5,main] 28
Thread[Thread-2,5,main] 28
Thread[Thread-0,5,main] 28
Thread[Thread-3,5,main] 29
Thread[Thread-1,5,main] 28
Thread[Thread-2,5,main] 29
Thread[Thread-0,5,main] 29
Thread[Thread-3,5,main] 30
Thread[Thread-1,5,main] 29
Thread[Thread-1,5,main] 30
Thread[Thread-0,5,main] 30
Thread[Thread-2,5,main] 30
Thread[Thread-2,5,main] 31
Thread[Thread-2,5,main] 32
Thread[Thread-0,5,main] 31
Thread[Thread-3,5,main] 31
Thread[Thread-1,5,main] 31
Thread[Thread-2,5,main] 33
Thread[Thread-3,5,main] 32
Thread[Thread-0,5,main] 32
Thread[Thread-3,5,main] 33
Thread[Thread-1,5,main] 32
Thread[Thread-0,5,main] 33
Thread[Thread-2,5,main] 34
Thread[Thread-1,5,main] 33
Thread[Thread-2,5,main] 35
Thread[Thread-0,5,main] 34
Thread[Thread-3,5,main] 34
Thread[Thread-2,5,main] 36
Thread[Thread-0,5,main] 35
Thread[Thread-3,5,main] 35
Thread[Thread-1,5,main] 34
Thread[Thread-3,5,main] 36
Thread[Thread-2,5,main] 37
Thread[Thread-0,5,main] 36
Thread[Thread-1,5,main] 35
Thread[Thread-2,5,main] 38
Thread[Thread-1,5,main] 36
Thread[Thread-3,5,main] 37
Thread[Thread-0,5,main] 37
Thread[Thread-2,5,main] 39
Thread[Thread-0,5,main] 38
Thread[Thread-1,5,main] 37
Thread[Thread-3,5,main] 38
Thread[Thread-2,5,main] 40
Thread[Thread-3,5,main] 39
Thread[Thread-0,5,main] 39
Thread[Thread-1,5,main] 38
Thread[Thread-0,5,main] 40
Thread[Thread-1,5,main] 39
Thread[Thread-3,5,main] 40
Thread[Thread-1,5,main] 40
Thread[Thread-1,5,main] 41
Thread[Thread-0,5,main] 41
Thread[Thread-3,5,main] 41
Thread[Thread-2,5,main] 41
Thread[Thread-0,5,main] 42
Thread[Thread-3,5,main] 42
Thread[Thread-1,5,main] 42
Thread[Thread-2,5,main] 42
Thread[Thread-3,5,main] 43
Thread[Thread-0,5,main] 43
Thread[Thread-2,5,main] 43
Thread[Thread-1,5,main] 43
Thread[Thread-2,5,main] 44
Thread[Thread-0,5,main] 44
Thread[Thread-3,5,main] 44
Thread[Thread-1,5,main] 44
Thread[Thread-0,5,main] 45
Thread[Thread-1,5,main] 45
Thread[Thread-2,5,main] 45
Thread[Thread-3,5,main] 45
Thread[Thread-1,5,main] 46
Thread[Thread-3,5,main] 46
Thread[Thread-0,5,main] 46
Thread[Thread-2,5,main] 46
Thread[Thread-3,5,main] 47
Thread[Thread-2,5,main] 47
Thread[Thread-0,5,main] 47
Thread[Thread-1,5,main] 47
Thread[Thread-2,5,main] 48
Thread[Thread-0,5,main] 48
Thread[Thread-1,5,main] 48
Thread[Thread-3,5,main] 48
Thread[Thread-2,5,main] 49
Thread[Thread-3,5,main] 49
Thread[Thread-1,5,main] 49
Thread[Thread-0,5,main] 49
Thread[Thread-2,5,main] 50
Thread[Thread-0,5,main] 50
Thread[Thread-3,5,main] 50
Thread[Thread-1,5,main] 50
Thread[Thread-1,5,main] 51
Thread[Thread-0,5,main] 51
Thread[Thread-1,5,main] 52
Thread[Thread-3,5,main] 51
Thread[Thread-2,5,main] 51
Thread[Thread-0,5,main] 52
Thread[Thread-2,5,main] 52
Thread[Thread-3,5,main] 52
Thread[Thread-1,5,main] 53
Thread[Thread-3,5,main] 53
Thread[Thread-2,5,main] 53
Thread[Thread-1,5,main] 54
Thread[Thread-0,5,main] 53
Thread[Thread-2,5,main] 54
Thread[Thread-1,5,main] 55
Thread[Thread-0,5,main] 54
Thread[Thread-3,5,main] 54
Thread[Thread-0,5,main] 55
Thread[Thread-3,5,main] 55
Thread[Thread-1,5,main] 56
Thread[Thread-2,5,main] 55
Thread[Thread-1,5,main] 57
Thread[Thread-0,5,main] 56
Thread[Thread-2,5,main] 56
Thread[Thread-3,5,main] 56
Thread[Thread-1,5,main] 58
Thread[Thread-3,5,main] 57
Thread[Thread-2,5,main] 57
Thread[Thread-0,5,main] 57
Thread[Thread-0,5,main] 58
Thread[Thread-2,5,main] 58
Thread[Thread-1,5,main] 59
Thread[Thread-3,5,main] 58
Thread[Thread-3,5,main] 59
Thread[Thread-1,5,main] 60
Thread[Thread-2,5,main] 59
Thread[Thread-0,5,main] 59
Thread[Thread-3,5,main] 60
Thread[Thread-0,5,main] 60
Thread[Thread-2,5,main] 60
Thread[Thread-2,5,main] 61
Thread[Thread-1,5,main] 61
Thread[Thread-0,5,main] 61
Thread[Thread-2,5,main] 62
Thread[Thread-3,5,main] 61
Thread[Thread-1,5,main] 62
Thread[Thread-0,5,main] 62
Thread[Thread-3,5,main] 62
Thread[Thread-2,5,main] 63
Thread[Thread-1,5,main] 63
Thread[Thread-2,5,main] 64
Thread[Thread-3,5,main] 63
Thread[Thread-0,5,main] 63
Thread[Thread-1,5,main] 64
Thread[Thread-3,5,main] 64
Thread[Thread-2,5,main] 65
Thread[Thread-0,5,main] 64
Thread[Thread-1,5,main] 65
Thread[Thread-2,5,main] 66
Thread[Thread-3,5,main] 65
Thread[Thread-0,5,main] 65
Thread[Thread-1,5,main] 66
Thread[Thread-2,5,main] 67
Thread[Thread-0,5,main] 66
Thread[Thread-3,5,main] 66
Thread[Thread-1,5,main] 67
Thread[Thread-2,5,main] 68
Thread[Thread-3,5,main] 67
Thread[Thread-0,5,main] 67
Thread[Thread-1,5,main] 68
Thread[Thread-0,5,main] 68
Thread[Thread-2,5,main] 69
Thread[Thread-3,5,main] 68
Thread[Thread-0,5,main] 69
Thread[Thread-1,5,main] 69
Thread[Thread-3,5,main] 69
Thread[Thread-2,5,main] 70
Thread[Thread-0,5,main] 70
Thread[Thread-1,5,main] 70
Thread[Thread-3,5,main] 70
Thread[Thread-3,5,main] 71
Thread[Thread-2,5,main] 71
Thread[Thread-0,5,main] 71
Thread[Thread-1,5,main] 71
Thread[Thread-2,5,main] 72
Thread[Thread-3,5,main] 72
Thread[Thread-2,5,main] 73
Thread[Thread-3,5,main] 73
Thread[Thread-1,5,main] 72
Thread[Thread-0,5,main] 72
Thread[Thread-3,5,main] 74
Thread[Thread-0,5,main] 73
Thread[Thread-2,5,main] 74
Thread[Thread-1,5,main] 73
Thread[Thread-2,5,main] 75
Thread[Thread-3,5,main] 75
Thread[Thread-1,5,main] 74
Thread[Thread-0,5,main] 74
Thread[Thread-0,5,main] 75
Thread[Thread-1,5,main] 75
Thread[Thread-2,5,main] 76
Thread[Thread-3,5,main] 76
Thread[Thread-3,5,main] 77
Thread[Thread-2,5,main] 77
Thread[Thread-0,5,main] 76
Thread[Thread-1,5,main] 76
Thread[Thread-3,5,main] 78
Thread[Thread-2,5,main] 78
Thread[Thread-2,5,main] 79
Thread[Thread-0,5,main] 77
Thread[Thread-1,5,main] 77
Thread[Thread-3,5,main] 79
Thread[Thread-2,5,main] 80
Thread[Thread-1,5,main] 78
Thread[Thread-0,5,main] 78
Thread[Thread-3,5,main] 80
Thread[Thread-0,5,main] 79
Thread[Thread-1,5,main] 79
Thread[Thread-0,5,main] 80
Thread[Thread-1,5,main] 80
Thread[Thread-1,5,main] 81
Thread[Thread-3,5,main] 81
Thread[Thread-2,5,main] 81
Thread[Thread-1,5,main] 82
Thread[Thread-3,5,main] 82
Thread[Thread-0,5,main] 81
Thread[Thread-3,5,main] 83
Thread[Thread-0,5,main] 82
Thread[Thread-1,5,main] 83
Thread[Thread-2,5,main] 82
Thread[Thread-1,5,main] 84
Thread[Thread-3,5,main] 84
Thread[Thread-0,5,main] 83
Thread[Thread-2,5,main] 83
Thread[Thread-0,5,main] 84
Thread[Thread-2,5,main] 84
Thread[Thread-1,5,main] 85
Thread[Thread-3,5,main] 85
Thread[Thread-0,5,main] 85
Thread[Thread-3,5,main] 86
Thread[Thread-2,5,main] 85
Thread[Thread-3,5,main] 87
Thread[Thread-0,5,main] 86
Thread[Thread-2,5,main] 86
Thread[Thread-1,5,main] 86
Thread[Thread-3,5,main] 88
Thread[Thread-0,5,main] 87
Thread[Thread-1,5,main] 87
Thread[Thread-0,5,main] 88
Thread[Thread-3,5,main] 89
Thread[Thread-2,5,main] 87
Thread[Thread-0,5,main] 89
Thread[Thread-3,5,main] 90
Thread[Thread-2,5,main] 88
Thread[Thread-1,5,main] 88
Thread[Thread-0,5,main] 90
Thread[Thread-2,5,main] 89
Thread[Thread-1,5,main] 89
Thread[Thread-2,5,main] 90
Thread[Thread-1,5,main] 90
Thread[Thread-1,5,main] 91
Thread[Thread-3,5,main] 91
Thread[Thread-1,5,main] 92
Thread[Thread-2,5,main] 91
Thread[Thread-0,5,main] 91
Thread[Thread-1,5,main] 93
Thread[Thread-0,5,main] 92
Thread[Thread-3,5,main] 92
Thread[Thread-2,5,main] 92
Thread[Thread-3,5,main] 93
Thread[Thread-0,5,main] 93
Thread[Thread-1,5,main] 94
Thread[Thread-2,5,main] 93
Thread[Thread-1,5,main] 95
Thread[Thread-0,5,main] 94
Thread[Thread-2,5,main] 94
Thread[Thread-3,5,main] 94
Thread[Thread-2,5,main] 95
Thread[Thread-0,5,main] 95
Thread[Thread-1,5,main] 96
Thread[Thread-3,5,main] 95
Thread[Thread-0,5,main] 96
Thread[Thread-3,5,main] 96
Thread[Thread-1,5,main] 97
Thread[Thread-2,5,main] 96
Thread[Thread-3,5,main] 97
Thread[Thread-2,5,main] 97
Thread[Thread-0,5,main] 97
Thread[Thread-1,5,main] 98
Thread[Thread-2,5,main] 98
Thread[Thread-1,5,main] 99
Thread[Thread-3,5,main] 98
Thread[Thread-0,5,main] 98
Thread[Thread-3,5,main] 99
Thread[Thread-0,5,main] 99
Thread[Thread-1,5,main] 100
Thread[Thread-2,5,main] 99
Thread[Thread-0,5,main] 100
Thread[Thread-3,5,main] 100
Thread[Thread-2,5,main] 100

Gibt was, das nennt sich CyclicBarrier
https://docs.oracle.com/en/java/javase/13/docs/api/java.base/java/util/concurrent/CyclicBarrier.html
und bietet sich geradezu prädestiniert dafür an.

A synchronization aid that allows a set of threads to all wait for each other to reach a common barrier point. CyclicBarriers are useful in programs involving a fixed sized party of threads that must occasionally wait for each other.

1 Like

Danke TMII, CyclicBarrier ist der deutlich zutreffendere Begriff, anstatt number2. Ich wusste nicht, dass es da schon etwas Fertiges gibt.
Nebenbei ist mir noch aufgefallen, dass number2 eigentlich vom Typ AtomicInteger hätte sein sollen, da ja theoretisch und praktisch bei number2++; etwas hätte schieflaufen können.

Danke für die Antwort, aber bei mir funktioniert leider nicht, also die Reihenfolge wird nicht eingehalten.

also wen die erste 10 Threads ausführt, die anderen müssen warten. Wenn diese erste 10 Threads fertig sind, dann müssen sie auf anderen warten

Das ist korrekt, denn die Lösung von CB setzt nicht auf eine Barrier (hier: CyclicBarriere, wie von @TMII korrekt referenziert), sondern auf einen Zufall, der daher kommt, dass die Threads zwischen durch 1 Sekunde warten.

Die Implementierung von CB ist demnach falsch. Du musst die von @TMII verwenden.

Das hat damit auch überhaupt nichts zu tun.

Bitte warte eben, ich passe das Beispiel etwas korrekter an.

Gruß,
Martin

1 Like

Bitte genauer beschreiben, wieso es bei dir nicht funktioniert… (Bei mir klappt’s nämlich, auch wenn ich Thread.sleep herausnehme)

Nein, ist sie nicht.

also, angenommen Thread-0 anfängt:
er zählt bis 10, dann er muss Pause machen und der andere, kann Thread-1 oder Thread-2 sein, reinkommen muss und weiterzählen bis 20, dann muss andere reinkommen usw.

deine Quellcode funktioniert nicht so. bitte verstehe mich nicht schlecht, ich bin trotzdem sehr sehr dankbar

Hast du die Synchronisierung über die gesamte Methode noch drin? Dann kann es auch nicht funktionieren… Du musst wenn, dann nur den kritischen Abschnitt synchronisieren.

ich habe dein Quellcode genau so laufen lasse, wie du es geschrieben hast.

Hi, hier die korrekte Umsetzung des Problems mit dem von @TMII geposteten Beispiels und der Anforderung an die Aufgabe.

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;

public class NumberRunner {

final CyclicBarrier barrier;

/**
 * Innere Klasse, die die Arbeit macht. 
 *
 * @author Marcinek
 *
 */
class Worker implements Runnable {
	private int number;


	public Worker(int n) {
		number = n;
	}

	@Override
	public void run() {
		for (int i = 0; i < 1000; i++) {
			System.out.println("Thread " + number + ": " + i);

			// Alle 10 soll gewartet werden. Hier sagt man an der Barrier, dass gewartet wird.
			// Die Barriere siehe unten ist so eingestellt, dass sie auf 3 Threads wartet, bevor es weiter geht.
			if(i % 10 == 0) {
				try {
					barrier.await();
				} catch (InterruptedException ex) {
					return;
				} catch (BrokenBarrierException ex) {
					return;
				}
			}
		}
	}
}

public NumberRunner () {
     barrier = new CyclicBarrier(NUMBER);
}

private final static int NUMBER = 3;

public static void main(String[] args) throws InterruptedException {
	
	NumberRunner numberRunner = new NumberRunner();
	
	Thread[] runner = new Thread[NUMBER];
	for (int i = 0; i < NUMBER; i++) {
		runner[i] = new Thread(numberRunner.new Worker(i));
	}
	for (int i = 0; i < NUMBER; i++) {
		runner[i].start();
	}

	for (int i = 0; i < NUMBER; i++) {
		runner[i].join();
	}

}
}

@CyborgBeta: Wenn du es einfach nicht weißt, dann poste hier bitte nicht Quellcode, dass den TO einfach total verwirrt. Das hat auch nix mit Provokationen zu tun, sondern ist einfach mal fakt. Deine Lösung hat nix mit der Aufgabe zu tun und erstellt, wie bereits gesagt, einfach per Zufall die richtige Antwort.

Hierzu benötigst du eine Verwaltung über alle Threads zusätzlich. Mein Beispiel beachtet das nicht. Das ist auch ggf. eine andere Anforderung, die eine CyclicBarrier unnötig macht.

Und normalerweise willst du so ein Verhalten auch nicht haben, weil das im Ergebniss eine Sequenzielle Verarbeitung wäre, wenn immer nur ein Thread tätig wäre.

2 Likes

@Adriano10 Was verstehst du unter warten? Wie lange soll gewartet werden, bis alle Threads weiterlaufen sollen?

Edit:
Also jetzt möchte ich schon gerne wisse, was hieran nicht wie gewünscht funktionieren soll:

import java.util.concurrent.atomic.AtomicInteger;

public class NumberRunner extends Thread {

	private static final int numberOfThreads = 4;

	private static volatile AtomicInteger cyclicBarrier = new AtomicInteger(0);
	private int number1 = 1;

	@Override
	public void run() {
		try {
			while (number1 <= 100) {
				// we synchronize the output, even if this isn't necessary
				synchronized (cyclicBarrier) {
					System.out.println(this.toString() + " " + number1);
				}
				if (number1 % 10 == 0) {
					cyclicBarrier.incrementAndGet();
					while (cyclicBarrier.get() < number1 / 10 * numberOfThreads) {
						// wait 10 seconds to avoid busy waiting
						// it could be also any other sleep time
						Thread.sleep(10);
					}
				} else {
					// the else block is optional
					Thread.sleep(1);
				}
				number1++;
			}
		} catch (InterruptedException ignore) {
		}
	}

	public static void main(String[] args) {
		for (int i = 0; i < numberOfThreads; i++) {
			new NumberRunner().start();
		}
	}

}

Nur für den Fall, das das jemand liest, und der Ansicht ist, dass diese Frage eine Antwort wert wäre:

  • „Funktioniert auf meinem Rechner bei ein paar Tests“ ist nicht genug
  • Einfach mal so ein volatile reinmischen, nur weil es um Threads geht, ergibt keinen Sinn
  • „we synchronize the output, even if this isn’t necessary“ muss wohl nicht weiter kommentiert werden
  • Ein Thread.sleep reinzumischen, um (für meinen Rechner, bei meinem Test) die richtige Ausgabe zu erhalten ist nicht die richtige Herangehensweise (sowas wie Thread.sleep(1) macht praktisch nie Sinn).

Die ganzen High-level Klassen und Methoden aus dem java.util.concurrent package dienen (etwas suggestiv gesagt) genau dem Zweck, dass man volatile, synchronized, sleep (und, der Vollständigkeit halber, auch wait, notify und notifyAll) nicht mehr in „normalem“ Code verwenden muss. Man sollte grob wissen, was das alles ist, und im Rahmen einer Grundlagenveranstaltung, wo es um Threads & Co geht, kann man mal sowas wie eine Semaphore, ein CoundDownLatch oder einen BlockingQueue „per Hand“ implementieren. Aber bevor man sich https://docs.oracle.com/javase/specs/jls/se7/html/jls-17.html oder http://www.angelikalanger.com/Articles/Topics.html#ConcurrentJava durchliest, und sich anmaßt, das in aller Tiefe zu verstehen, sollte man sich (je nach Zusammenhang) lieber darauf verlassen, dass der Code, den absolute Experten geschrieben haben und der Millionenfach verwendet und time-tested ist, das tut, was er tun soll.

2 Likes

jetzt funktioniert, danke dir