Threads notify

minzee

Bekanntes Mitglied
Hi :)

Schon wieder eine Frage zu Threads. Dieses mal zu notify.

Wenn ich mein Buch richtig verstanden habe, weckt nofity einen beliebigen Thread auf, der mittels wait in einen Schlafmodus versetzt wurde. Es muss angeblich nicht unbedingt jener Thread sein, der schon am längsten schläft.

Jetzt wollte ich das ausprobieren mit folgenden Programm:

Java:
class R // von Threads gemeinsam genutzte Resource
{
   public synchronized void mWait(String name)
   {
      System.out.println("wait a "+name); // Ausgabe
      try
      {
         wait();
      }
      catch(InterruptedException e)
      {
         System.out.println("wait interrupt "+name);
      }
      System.out.println("wait b "+name); // Ausgabe
   }
   public synchronized void mNotify(String name)
   {
      System.out.println("---------------------notify a "+name); // Ausgabe
      notify();
      System.out.println("---------------------notify b "+name); // Ausgabe
   }
}

class TWait extends Thread // ein Thread, der in den Schlafmodus versetzt wird
{
   private R r;
   public TWait(R r, String name)
   {
      super(name);
      this.r = r;
   }
   public void run()
   {
      r.mWait(getName());
   }
}

class TNotify extends Thread // ein Thread, der irgendeinen anderen Thread aus den Schlafmodus holen soll
{
   private R r;
   public TNotify(R r)
   {
      this.r = r;
   }
   public void run()
   {
      r.mNotify(getName());
   }
}

public class Main
{
   public static void main(String[] args)
   {
      R r = new R();
      
      // 100 Wait-Threads:
      int size = 100;
      TWait[] threads = new TWait[size];
      for(int i = 0; i < size; ++i)
      {
         threads[i] = new TWait(r, Integer.toString(i));
      }
      for(int i = 0; i < size; ++i) // benötigt 100 * 10 ms = 1000 ms = 1 s
      {
         threads[i].start();
         try
         {
            Thread.sleep(10); // 10 ms
         }
         catch(InterruptedException e)
         {
            System.out.println("sleep interrupt");
         }
      }
      
      // 1 Notify-Thread:
      TNotify t = new TNotify(r);
      t.start();
   }
}

Aber egal, wie oft ich das Programm starte, der notify weckt immer nur den zuerst angelegten Thread aus seinen Schlafmodus auf. Wie kann ich denn Java dazu bringen, dass mir mal ein beliebig anderer zufällig ausgewählter Thread aufgeweckt wird?
 
Zuletzt bearbeitet:

Bug Fisher

Bekanntes Mitglied
minzee hat gesagt.:
Aber egal, wie oft ich das Programm starte, der notify weckt immer nur den zuerst angelegten Thread
Die Docu sagt auch nur:
http://docs.oracle.com/javase/7/docs/api/java/lang/Object.html#notify%28%29 hat gesagt.:
Wakes up a single thread that is waiting on this object's monitor. If any threads are waiting on this object, one of them is chosen to be awakened. The choice is arbitrary and occurs at the discretion of the implementation.

Da green threads offensichtlich verworfen wurden, musst du, wenn ich das richtig verstehe, eher gucken, wie (und warum) dein OS das macht. Green threads - Wikipedia, the free encyclopedia

Hast du es schon mit wirklich vielen Threads versucht (so >10000) ?
 
Zuletzt bearbeitet:

minzee

Bekanntes Mitglied
Ich glaub, ich hab das falsch programmiert :(
Bei 10000 wird auch wieder nur Thread 0 aufgeweckt.
 
Zuletzt bearbeitet:

Joose

Top Contributor
Was sagen denn deine Ausgaben? Kommen die anderen Threads überhaupt zum "wait" bevor der 1.Thread wieder per notify geweckt wird? Ich glaube dein Problem liegt am synchronized synchronized with wait
 
Zuletzt bearbeitet:

Bug Fisher

Bekanntes Mitglied
minzee hat gesagt.:
Ich glaub, ich hab das falsch programmiert
Um Gottes Willen, nein, das heisst das nicht; hat mich nur interessiert; dein Code scheint schon korrekt zu sein.

Alles was ich geschrieben habe meint am Ende nur, dass es (zumindest aus der Sicht der JRE) "arbitrary" sein wird, welcher Thread aufgeweckt wird.

Lass doch den Block
Java:
Thread.sleep(10); // 10 ms
mal weg, vielleicht hast du dann "Erfolg", dass es mal "ungeordnet" läuft :)
Wenn nicht ist es natürlich immer noch nicht falsch.

Am besten erledigst du das Erzeugen und Starten direkt hintereinander in der ersten Schleife.
 

minzee

Bekanntes Mitglied
Den sleep-Befehl hab ich absichtlich eingebaut, damit es ganz klar ist, in welcher Reihenfolge die Threads angelegt werden. Das soll eindeutig sein. Sonst kann ich nicht erkennen, dass wait wirklich IRGENDEINEN schlafenden Thread weckt.
 
Zuletzt bearbeitet:

Bug Fisher

Bekanntes Mitglied
Ich habe das hier mal aufs Nötige zusammengeschrumpft, sollte aber aufs gleiche rauskommen.

Bei meinem 64bit linux wird nicht immer nur t0 geweckt.

Am Ende geht es um das riesen Thema scheduler, und da ist die Docu trotzdem weiterhin richtig, denn arbitrary kann auch heissen immer der zuerst erstellte Thread. Das ganze ist von so vielen Faktoren abhängig, dass es eben nicht deterministisch ist; wenn du es nicht schafftst das zu reproduzieren, dann musst du es einfach erstmal glauben :) Denn die Realität ist nicht so minimalistisch wie unsere beiden Beispiele.

-> Du hast vier Kerne, dabei sind zwei "nur hyperthreaded", 27 Prozesse am laufen, die 27 Prozesse haben gerade insgesamt 13 zusätzliche Threads gestartet und dann kommen noch asynchrone interrupts von Maus und Netzwerkkarte hinzu. Wer darf wann eine wie grosse Zeischeibe haben ? Willst du Akku sparen oder die größte Primzahl scnell finden? Muss vielleicht erst die Schranke runter bevor der Zug kommt ? Soll die Musik auf keinen Fall Aussetzer haben ?

Java:
public class Main {
	public static void main(final String... args) throws Exception {
		final Object o = new Object();
		final Thread[] t = new Thread[16000];
		
		for(int i = 0; i < t.length; ++i) {
			t[i] = new Thread(createRunnable(o), "t"+i);
			t[i].start();
		}
		
		synchronized(o) {
			o.notify();
		} 
	}
	
	private static Runnable createRunnable(final Object monitor) {
		return new Runnable() {
			@Override
			public void run() {
				try {
					int N = (int)Math.random()*1000000 + 10000;
					for(int i = 0; i < N; ++i) {
						i += 1;
						i -=1;
					}
					
					synchronized(monitor) {
						monitor.wait();						
					}
					
					System.out.println(Thread.currentThread().getName() + " needed to get up now");
					System.exit(0);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		};
	}
}
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
I Threads Multithreading, Producer/Consumer, notify() Java Basics - Anfänger-Themen 6
O Threads - Synchronize(), join(), wait(), notify(), yield() Java Basics - Anfänger-Themen 6
ralfb1105 Frage zu Thread Synchronisation mit wait() und notify() Java Basics - Anfänger-Themen 3
kilopack15 Verständnisfrage zur Verwendung von notify() bei Threads Java Basics - Anfänger-Themen 2
M notify und wait Java Basics - Anfänger-Themen 1
M Threads notify/notifyAll Philosophen-Problem Java Basics - Anfänger-Themen 14
D Stack-Objekt - LIFO - wait(); notify(); Java Basics - Anfänger-Themen 0
D Probleme mit wait(), notify() Java Basics - Anfänger-Themen 0
M wait/notify bei Socket Java Basics - Anfänger-Themen 4
T Alle Threads .notify() Java Basics - Anfänger-Themen 13
Luk10 Monitor: wait() und notify() Java Basics - Anfänger-Themen 8
S Threads: wait() und notify() Java Basics - Anfänger-Themen 11
M lock notify synchronisation Java Basics - Anfänger-Themen 8
S Problem mit notify() Java Basics - Anfänger-Themen 4
S bin zu blöd für threads - wait, notify, synchronized Java Basics - Anfänger-Themen 11
B Problem: wait() -> notify() Java Basics - Anfänger-Themen 4
M Threads, wait() und notify() Java Basics - Anfänger-Themen 10
G Threads steuern mit wait und notify Java Basics - Anfänger-Themen 2
P wait und notify oder wie soll ich es lösen Java Basics - Anfänger-Themen 2
M Warum kann man dem Thread kein notify senden? Java Basics - Anfänger-Themen 15

Ähnliche Java Themen

Neue Themen


Oben