{"id":6881,"date":"2015-12-28T09:59:45","date_gmt":"2015-12-28T08:59:45","guid":{"rendered":"https:\/\/www.herr-rau.de\/wordpress\/?p=6881"},"modified":"2025-03-15T11:24:36","modified_gmt":"2025-03-15T10:24:36","slug":"threads-iii-erzeuger-verbraucher-und-ein-neuer-zustand","status":"publish","type":"post","link":"https:\/\/www.herr-rau.de\/wordpress\/2015\/12\/threads-iii-erzeuger-verbraucher-und-ein-neuer-zustand.htm","title":{"rendered":"Threads III &#8211; Erzeuger, Verbraucher und ein neuer Zustand"},"content":{"rendered":"<div style='text-align:right;'><small>(<a href='https:\/\/www.herr-rau.de\/wordpress\/2015\/12\/threads-iii-erzeuger-verbraucher-und-ein-neuer-zustand.htm#comments'>1 Kommentare.<\/a>)<\/small> <\/div>\n<p>(<a href=\"https:\/\/www.herr-rau.de\/wordpress\/2015\/12\/threads-ii-java-und-ein-wenig-nebenlaeufigkeit.htm\">Fortsetzung von hier.<\/a>) Im bisherigen Beispiel ging es um Toilettenbenutzer, die auf eine leere Toilette warten, sie dann auf jeden Fall benutzen k\u00f6nnen und auf jeden Fall wieder herausgehen, so dass die Toilette dann f\u00fcr den n\u00e4chsten Besuch wieder frei ist. Wir hatten quasi Erzeuger, die den kritischen Bereich betreten, wo auf jeden Fall Platz zum, \u00e4h, Erzeugen ist, und dann gehen sie wieder. Das erzeugte Produkt bleibt nicht etwa in der Toilette, sondern verschwindet im Orkus.<br>Daf\u00fcr reichen unsere bisherigen synchronisierten Methoden.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Erzeuger und Verbraucher<\/h3>\n\n\n\n<p>Wir erweiterten jetzt unsere Aufgabe zu etwas, das allgemein Erzeuger-Verbraucher-Problem hei\u00dft. Dazu stellen wir uns einen oder mehrere Erzeuger vor, die ein Produkt erstellen und das an einem Speicherort abstellen wollen, <em>das aber nur k\u00f6nnen, wenn dort Platz ist.<\/em> Dazu kommen noch ein oder mehrere Verbraucher, die regelm\u00e4\u00dfig diesen gemeinsamen Speicherort aufsuchen, um von dort ein Produkt abzuholen &#8211; <em>das geht nat\u00fcrlich nur, wenn dort auch ein Produkt f\u00fcr sie liegt.<\/em><\/p>\n\n\n\n<p>Damit kommt ein neuer Faktor hinzu. Nicht nur gibt es einen kritischen Bereich, der nur von einem (sagen wir mal) auf einmal betreten werden darf. Au\u00dferdem gibt es in diesem Bereich noch eine weitere Bedingung, die erf\u00fcllt sein muss: der Lieferant muss dort Platz f\u00fcr sein Produkt haben, und der Abholer muss dort eine Kiste zum Abholen vorfinden.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"698\" height=\"90\" src=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/threads_erz-verb.png\" alt=\"threads_erz-verb\" class=\"wp-image-6932\" srcset=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/threads_erz-verb.png 698w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/threads_erz-verb-150x19.png 150w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/threads_erz-verb-550x71.png 550w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/threads_erz-verb-660x85.png 660w\" sizes=\"auto, (max-width: 698px) 100vw, 698px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">L\u00f6sung 1 (keine gute L\u00f6sung)<\/h3>\n\n\n\n<p>In einer Schleife produziert der Erzeuger immer wieder ein Produkt (im Beispiel eine Kiste) und ruft danach die synchronisierte Methode <code>hineinlegen(Kiste)<\/code> des Speicher-Objekts (der ein Monitor ist) auf. Damit hat er ein Exklusivrecht auf die vom Monitor \u00fcberwachten Methoden. Wenn dort kein Platz zum Ablegen der Kiste ist, dann hilft einfaches Warten (in einer Schleife etwa) auch nicht: Der Verbraucher kann ja nicht hinein, um die Kiste dort herauszuholen, solange der Erzeuger die Monitormethode benutzt.<\/p>\n\n\n\n<p>Ebenso der Verbraucher: Wenn der die Methode <code>herausholen()<\/code> aufruft, die als R\u00fcckgabetyp eine Kiste hat, was soll dann passieren, wenn gar keine Kiste im Speicher ist? Einfaches Warten auf eine Kiste funktioniert ebenso wenig wie oben.<\/p>\n\n\n\n<p>Eine L\u00f6sung ist: Nu, wenn keine Kiste da ist, dann gibt die Methode herausholen einfach <code>null<\/code> zur\u00fcck statt einer Kiste. Das hei\u00dft aber, dass der Verbraucher komplizierter wird: Er kann nicht sichergehen, dass er nach dem Holen eine Kiste hat und muss, wenn er stattdessen <code>null<\/code> hat, diesen einen Kistenholversuch solange wiederholen, bis er doch eine Kiste hat. Dann kann er regul\u00e4r weitermachen.<br>Ebenso der Erzeuger: Wenn der eine Kiste hineinlegen will, gibt es \u00fcblicherweise keinen R\u00fcckgabetyp (<code>void<\/code>). Man m\u00fcsste stattdessen eine R\u00fcckgabe machen, boolean oder die Kiste selber, anhand derer der Erzeuger unterscheiden kann, ob der Hineinlegen-Versuch erfolgreich war oder nicht. Wenn nicht, wird der Versuch mit der urspr\u00fcnglichen Kiste solange wiederholt, bis der Erzeuger sie doch los wird. Dann kann er regul\u00e4r weitermachen.<\/p>\n\n\n\n<p>Diese L\u00f6sung funktioniert. Aber zum einen ist der Code dann etwas umst\u00e4ndlich, zum anderen f\u00fchrt das dazu, dass der Erzeuger m\u00f6glicherweise immer und immer wieder versucht eine Kiste abzuliefern, auch wenn der Verbraucher noch so langsam arbeitet. (Oder umgekehrt.) Jeder Thread l\u00e4uft st\u00e4ndig in einer Schleife, auch wenn gar nichts passiert. Das kostet Rechenzeit.<\/p>\n\n\n\n<p>Deshalb macht man das anders.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">L\u00f6sung 2: Ein neuer Zustand<\/h3>\n\n\n\n<p>Wenn ein Erzeuger-Thread die synchronisierte <code>hineinlegen<\/code>-Methode aufruft, dort aber keinen Platz findet, dann wird er ruhen geschickt. Damit gibt er, wichtig, seinen exklusiven Anspruch auf den Monitor vorl\u00e4ufig auf.<\/p>\n\n\n\n<p>Wenn dann mal endlich ein Verbraucher die Kiste abholt und Platz im Speicher-Bereich schafft, muss der Speicher\/Monitor danach dem Betriebssystem sagen, dass dies alle von ihm ruhen geschickten Threads aufwecken soll. Auch der ruhende Erzeuger wird so geweckt und versucht dann a) wieder exklusiven Anspruch auf den Monitor zu kriegen (falls das nicht klappt, ist er BLOCKED, siehe vorherigen Eintrag) und im Erfolgsfall b) macht er an genau der Stelle weiter, an der er ruhen geschickt wurde.<\/p>\n\n\n\n<p>Dieser neue Zustand hei\u00dft WAITING:<\/p>\n\n\n\n<p><br><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"1201\" height=\"374\" src=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/Threads_2_large_alternative_verbessert.png\" alt=\"\" class=\"wp-image-64492\" srcset=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/Threads_2_large_alternative_verbessert.png 1201w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/Threads_2_large_alternative_verbessert-300x93.png 300w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/Threads_2_large_alternative_verbessert-700x218.png 700w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/Threads_2_large_alternative_verbessert-150x47.png 150w\" sizes=\"auto, (max-width: 1201px) 100vw, 1201px\" \/><\/figure>\n\n\n\n<p>Erzeuger und Verbraucher sehen im einfachsten Fall so aus:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public class Erzeuger extends Thread  {<br>  \/\/ Attribute<br>  Speicher speicher;<br>  int produktionsnummer = 0;<br><br>  \/\/Konstruktor<br>  public Erzeuger(Speicher speicher) {<br>    this.speicher = speicher;<br>  }<br><br>  \/\/Methoden<br>  public void run() {<br>    while (produktionsnummer&lt;20) {<br>      Kiste k = new Kiste(produktionsnummer);<br>      produktionsnummer++;<br>      speicher.hineinlegen(k);<br>    }<br>  }<br>}<\/code><\/pre>\n\n\n\n<pre class=\"wp-block-code\"><code>public class Verbraucher extends Thread{\n    \/\/ Attribute\n    Speicher speicher;\n\n    \/\/Konstruktor\n    public Verbraucher(Speicher speicher) {\n        this.speicher = speicher;\n    }\n\n    \/\/Methoden\n    public void run() {\n        while (true) {\n            Kiste k = speicher.herausholen();\n        }\n    }\n}<\/code><\/pre>\n\n\n\n<p>Klar wird man noch ein <code>sleep()<\/code> einbauen, damit das nicht gar so schnell geht, und da und dort ein <code>System.out.println()<\/code>, damit man auch etwas mitkriegt davon, ob gerade eine Kiste produziert oder dem Speicher entnommen wurde, aber das ist eigentlich nur Dekoration.<\/p>\n\n\n\n<p>Schwieriger finde ich die Programmierung des Monitors:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public class Speicher {\n  \/\/ Attribute\n  boolean istLeer = true;\n  Kiste eingelagerteKiste = null;\n\n  \/\/Konstruktor\n  public Speicher() {\n  }\n\n  \/\/Methoden\n  synchronized void hineinlegen(Kiste neueKiste) {        \n    while (!istLeer) { \n      \/\/exklusiver Zugang gelungen, aber fruchtlos\n      try {\n        wait(); \/\/geh ruhen\n      }\n      catch (Exception e) { System.out.println(e); }\n    }\n    \/\/exklusiver Zugang gelungen, und sinnvoll\n    istLeer = false;\n    eingelagerteKiste = neueKiste;\n    notifyAll(); \/\/Wecken der ruhenden Threads\n  }\n\n  synchronized Kiste herausholen() {\n    while (istLeer) {\n      \/\/exklusiver Zugang gelungen, aber fruchtlos\n      try {\n        wait(); \/\/geh ruhen\n      }\n      catch (Exception e) { System.out.println(e); }\n    }\n    \/\/exklusiver Zugang gelungen und sinnvoll\n    istLeer = true;\n    notifyAll(); \/\/Wecken der ruhenden Threads\n    return eingelagerteKiste;\n  }\n}<\/code><\/pre>\n\n\n\n<p>Mit dem <code>wait()<\/code> in Zeile 15 und 29 wird der Thread, der diesen Befehl ausl\u00f6st, in unseren neuen WAITING-Zustand versetzt. Das muss aus Java-Gr\u00fcnden in einem try-catch-Block geschehen. Das <code>notifyAll()<\/code> in Zeile 22 und 35 sagt dem Betriebssystem, dass wartende Threads jetzt geweckt werden sollen, auf dass sie erneut ihr Gl\u00fcck versuchen.<\/p>\n\n\n\n<p>Erkl\u00e4ren muss man jetzt nur die Schleifen um das <code>wait()<\/code> herum, siehe Zeilen 12 und 26. Warum reicht da nicht ein einfaches <code>if<\/code>?<\/p>\n\n\n\n<p>F\u00fcr diesen Fall:<br>Ein Erzeuger will die exklusive <code>hineinlegen<\/code>-Methode aufrufen. Der Monitor ist gerade frei, der Erzeuger also nicht <code>BLOCKED<\/code>, und trifft auf die Schleife, deren Bedingung wahr ist (der Speicher ist voll), so dass der Erzeuger in Winterschlaf versetzt wird (<code>WAITING<\/code>).<br>Ein Verbraucher holt dann die Kiste heraus und alle schlafenden Threads werden geweckt. Auch unser erster Thread wird geweckt (ist <code>RUNNABLE<\/code>), doch ebenso ein zweiter Erzeuger. Der zweite kommt zuerst dran (ist <code>RUNNING<\/code>), kriegt exklusiven Zugang zum Monitor, legt eine Kiste ein, und verl\u00e4sst den kritischen Bereich. Jetzt erst kommt unser erster Thread an den Zug (<code>RUNNING<\/code>), er kriegt seinen exklusiven Zugang zum Monitor &#8211; dummerweise ist aber schon wieder kein Platz mehr f\u00fcr die Kiste! Also muss er wieder ruhen und auf das n\u00e4chste Wecken warten.<\/p>\n\n\n\n<p>Will hei\u00dfen: Zum Zeitpunkt des Weckens ist die f\u00fcr den Erzeuger kritische Bedingung (dass Platz in der Ablage ist) zwar erf\u00fcllt, aber schon kurz danach, wenn der Erzeuger zum Zug kommt, kann sie schon wieder nicht mehr erf\u00fcllt sein.<\/p>\n\n\n\n<p><strong><br>Aufgaben:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Legen Sie ein Projekt an mit den Klassen Speicher, Erzeuger, Verbraucher und Starter und testen Sie es.<\/li>\n\n\n\n<li>Testen Sie das mit mehreren Erzeugern und Verbrauchern.<\/li>\n\n\n\n<li>\u00c4ndern Sie die Klasse Speicher so, dass dort Platz f\u00fcr drei Kisten ist. Sie brauchen dazu ein Feld der L\u00e4nge 3 und ein Attribut, das angibt, ob Platz f\u00fcr eine neue Kiste ist, und ein zweites, das angibt, ob eine Kiste zum Abholen da ist.<\/li>\n<\/ul>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h3 class=\"wp-block-heading\">Bonus f\u00fcr die, die dabeigeblieben sind<\/h3>\n\n\n\n<p>Man kann die Zust\u00e4nde der laufenden Threads sch\u00f6n sichtbar machen. Die Klasse Thread (und damit ihre Unterklassen ebenso) hat in Java eine Methode <code>getState()<\/code>, die als R\u00fcckgabe eine Enum Thread.State hat, n\u00e4mlich einen der folgenden Werte: <code>NEW, RUNNABLE, TERMINATED, TIMED_WAITING, BLOCKED, WAITING.<\/code> Nicht dabei ist <code>RUNNING<\/code>.<br>Ich habe mir eine Klasse ThreadObserver geschrieben, das sind einige ihre wichtigsten Methoden:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"192\" height=\"120\" src=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/ThreadObserver_kurz.png\" alt=\"ThreadObserver_kurz\" class=\"wp-image-6956\" srcset=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/ThreadObserver_kurz.png 192w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/ThreadObserver_kurz-150x94.png 150w\" sizes=\"auto, (max-width: 192px) 100vw, 192px\" \/><\/figure>\n\n\n\n<p>Man kann mit <code>addToWatchlist<\/code> bestehende Threads zu einer Liste beobachteter Threads hinzuf\u00fcgen. Falls diese Threads noch nicht laufen, kann man sie mit <code>startAllThreads<\/code> laufen lassen. Threads, die nicht im Zustand <code>NEW<\/code> sind, werden dabei ignoriert, die laufen oder liefen ja schon. Mit <code>stopEverything<\/code> werden sowohl alle Threads als auch der Beobachter selber abgebrochen. Wenn man das vergisst, kann es leicht passieren, dass der eine oder andere Thread unbemerkt weiterl\u00e4uft. Und mit <code>startWriting<\/code> schaltet man das Protokollieren ein.<\/p>\n\n\n\n<p>Das Protokollieren: Der ThreadObserver fragt regelm\u00e4\u00dfig alle beobachteten Threads nach ihrem Zustand. Wenn sich der \u00e4ndert (und um das feststellen zu k\u00f6nnen, muss der vorhergehende Zustand gespeichert worden sein), dann wird diese Information zur Zeit an ein selbstgeschriebenes ThreadStateWindow und an einen ThreadStatePrinter \u00fcbergeben; das erste gibt stellt die \u00c4nderung in einem Fenster dar, der zweite druckt sie auf die Konsole aus.<\/p>\n\n\n\n<p>Nat\u00fcrlich ist dabei nicht gew\u00e4hrleistet, dass wirklich jede \u00c4nderung sofort bemerkt wird. Der ThreadObserver nutzt schlie\u00dflich selber einen Thread, um die anderen zu beoachten, und wer wei\u00df, wie oft und wann der drankommt. Aber im Prinzip funktioniert das gut.<\/p>\n\n\n\n<p>Wenn man also seine Starterklasse von ThreadObserver erben l\u00e4sst:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>public class Starter extends ThreadObserver {\n  \/\/ Attribute\n  Speicher s;\n  Erzeuger e0;\n  Verbraucher v0;\n\n  \/\/Konstruktor\n  public Starter() {\n    s = new Speicher();\n    e0 = new Erzeuger(s);\n    v0 = new Verbraucher(s);\n  }\n\n  \/\/Methoden\n  public void starten() {\n    e0.setName(\"erzeuger0\");\n    v0.setName(\"verbraucher0\");        \n\n    addToWatchlist(e0);\n    addToWatchlist(v0);\n    startWriting();\n\n    e0.start();\n    v0.start();        \n  }\n}<\/code><\/pre>\n\n\n\n<p>&#8211; dann kriegt man die aktuellen Zust\u00e4nde von Erzeuger und Verbraucher angezeigt:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"476\" height=\"145\" src=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/ThreadObserver_window.png\" alt=\"ThreadObserver_window\" class=\"wp-image-6959\" srcset=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/ThreadObserver_window.png 476w, https:\/\/www.herr-rau.de\/wordpress\/archiv\/ThreadObserver_window-150x46.png 150w\" sizes=\"auto, (max-width: 476px) 100vw, 476px\" \/><\/figure>\n\n\n\n<p>Ein Problem ist allerdings, dass die Zust\u00e4nde <code>RUNNABLE<\/code> und <code>BLOCKED<\/code> so gut wie nie sichtbar werden. Klar: Wenn ein Erzeuger oder Verbraucher mal in den Speicher darf, ist seine Arbeit darin &#8211; es sind ja nur ein paar Zeilen Code &#8211; so schnell erledigt, dass er a) sofort danach wieder beim Erzeugen oder Verbrauchen ist (<code>TIMED_WAITING<\/code>) und b) ein eventuell geblockter Thread sofort wieder entblockt wird, laufen darf und dann wieder am Arbeiten ist (<code>TIMED_WAITING<\/code>).<\/p>\n\n\n\n<p>Eine L\u00f6sung ist die Klasse Zeitschinder mit einer (der Einfachheit halber statischen) Methode <code>zeitSchinden<\/code>. Die wird innerhalb der Speicher\/Monitor-Methoden aufgerufen. Darin wird mal eben die Fakult\u00e4t von 20000 berechnet, so dass die synchronisierten Methoden nicht gar so schnell ablaufen. Dann sieht man auch mehr Zust\u00e4nde:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"445\" height=\"145\" src=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/ThreadObserver_window.gif\" alt=\"ThreadObserver_window\" class=\"wp-image-6962\"\/><\/figure>\n\n\n\n<p><strong><br>Aufgaben:<\/strong><\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Warum ist immer nur h\u00f6chstens ein Thread gr\u00fcn? Kann man das \u00e4ndern?<\/li>\n\n\n\n<li>Warum endet das ganze immer damit, dass ein paar Threads grau angezeigt werden und ein paar orange?<\/li>\n\n\n\n<li>Was ist der Unterschied zwischen <code>sleep()<\/code> und <code>wait()<\/code>? Was der zwischen BLOCKED und WAITING?<\/li>\n\n\n\n<li>Bauen Sie den ThreadObserver in eines Ihrer Projekte ein, lassen Sie Ihren Starter davon erben und nutzen Sie dann die Methoden zum Hinzuf\u00fcgen und Protokollieren von Threads. Arbeiten Sie, falls Sie wollen, mit <code>Zeitschinder.zeitSchinden()<\/code> (<a href=\"https:\/\/www.herr-rau.de\/wordpress\/archiv\/ThreadObserverZeitschinder.zip\" rel=\"\">Download der beiden Java-Klassen<\/a>).<\/li>\n\n\n\n<li>Erkl\u00e4ren Sie mir, wieso bei mir manchmal ein Thread als BLOCKED gemeldet wird, selbst wenn im ganzen Projekt keine einzige synchronisierte Methode (oder synchronisierter Anweisungsblock) verwendet wird. Das verstehe ich selber noch nicht.<\/li>\n<\/ul>\n\n\n\n<p>Damit sind meine drei Blogeintr\u00e4ge zu Threads unter Java beendet, mit denen bin ich auch f\u00fcr den Flipped Classroom vorbereitet: Meine Sch\u00fclerinnen und Sch\u00fcler sollen sich das jeweils zu Hause durchlesen und die Aufgaben dazu dann in der Schule l\u00f6sen. Ich lerne selber ja auch aus aus Texten besser als aus Videos. Nat\u00fcrlich gibt es zu Threads noch mehr zu sagen, und Java bietet noch weitere M\u00f6glichkeiten zur Synchronisation an, aber viel mehr wei\u00df ich nicht und f\u00fcr die Schule reicht das eh. <s>Leider ist das Thema Threads im neuen Lehrplan weitgehend gestrichen. Da wird nur noch modelliert, aber nicht mehr implementiert &#8211; kein Java mehr, keine echte Umsetzung. Nun, dauert ja noch acht Jahre, bis der in der Oberstufe angelangt ist.<\/s> Nachtrag: Ja, dann kam ja doch alles anders mit dem G9 und der Oberstufeninformatik, so dass jetzt Threads weiterhin im mehr oder weniger gleichen Umfang Thema sind.<\/p>\n\n\n\n<p><em>Nachtrag: Neun Jahre sp\u00e4ter ist mir aufgefallen, dass ich gar nicht szu Verklemmungen geschrieben habe, deshalb <a href=\"https:\/\/www.herr-rau.de\/wordpress\/2024\/12\/threads-iv-deadlock.htm\">hier die Fortsetzung.<\/a><br><img loading=\"lazy\" decoding=\"async\" width=\"1\" height=\"1\" src=\"https:\/\/ssl-vg03.met.vgwort.de\/na\/b568e7bc8e804e0a9dd58129f47c23c3\" alt=\"\"><\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>(1 Kommentare.) (Fortsetzung von hier.) Im bisherigen Beispiel ging es um Toilettenbenutzer, die auf eine leere Toilette warten, sie dann auf jeden Fall benutzen k\u00f6nnen und auf jeden Fall wieder herausgehen, so dass die Toilette dann f\u00fcr den n\u00e4chsten Besuch wieder frei ist. Wir hatten quasi Erzeuger, die den kritischen Bereich betreten, wo auf jeden [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":6962,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[25],"tags":[227],"class_list":["post-6881","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-informatik","tag-informatik"],"jetpack_featured_media_url":"https:\/\/www.herr-rau.de\/wordpress\/archiv\/ThreadObserver_window.gif","jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/posts\/6881","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/comments?post=6881"}],"version-history":[{"count":4,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/posts\/6881\/revisions"}],"predecessor-version":[{"id":64494,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/posts\/6881\/revisions\/64494"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/media\/6962"}],"wp:attachment":[{"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/media?parent=6881"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/categories?post=6881"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.herr-rau.de\/wordpress\/wp-json\/wp\/v2\/tags?post=6881"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}