# viele Threads



## Titanpharao (12. Jan 2008)

Hi,
 ist es vorteilhaft, oder eher schlimm wenn man zum beispiel 100 Threads startet?

Wird das Programm daduch langsammer als wenn man die 100 dinge in einem machen würde?


----------



## Gast (12. Jan 2008)

prinzipiell braucht das erstellen eines Threads Zeit.

```
new Thread(someThingRunnable);
```

dadurch wird das ganze tendenziell langsamer.

Jeder Thread muß irgendwo seine Varibalen ablegen, sofern er welche benötigt. Speicherverbrauch steigt tendenziell an.

Richtig parallelität gibt es nicht. Der Prozessor rechnet erst an einem Thread herum, dann an einem anderen usw. Daher wird es hier auch eher keinen Geschwindigkeitsvorteil geben.

Greifen die Threads auf gleiche Resourcen zu kann es zu Problemen und inkonsistenzen geben.

Nutzt man die möglichkeit zur Synchronisation, kann eine bestimmte Resource während der Synchronisation nur von einem Thread genutzt werden, während die anderen warten.

Folge hierbei sind unter umständen deadlocks.

Ein klassisches Beispiel für das sinnvolle einsetzen von Threads macht das Drucken. 
Beispiel ohne Thread.
a. MainThread stellt eine Textverarbeitung zur Verfügung.
b. Der Klick auf Drucken macht das Dokument fertig und 
c. schickt es zum Drucker. 
d. Sobald das Drucken abgeschlossen ist. 
e. Kann die Textverarbeitung weiter genutzt werden.

Beispiel mit Thread.
a. siehe oben
b. startet neuen Thread.
             a2. Dokument wird fertig gestellt und zum Drucker geschickt...
c. Sobald der Thread gestartet wurde kann die Textverarbeitung weiter genutzt werden ohne auf das Ende des Druckvorgangs warten zu müssen.

Es kommt also ganz darauf an was du machen möchtest.


----------



## Guest (12. Jan 2008)

Das lässt sich pauschal nicht sagen, wobei 100 Threads wohl ein wenig viel ist (außer bei nem Webserver z.B.) ;-)

Allgemein ist die Verwendung von Threads weder "gut" noch "böse", es kommt darauf an ob sich eine parallele Verarbeitung deiner Daten lohnt bzw. überhaupt möglich ist.

Beschreibe doch mal, was du machen willst, dann kann dir bestimmt geholfen werden.


----------



## Titanpharao (12. Jan 2008)

Also ich habe minimum 100 Monster auf meinem Spielfeld(JPanel) laufen. 

Diese haben alle andere "Laufzeiten",also wann sie sich bewegen sollen. Dazu kommt noch das alle andere Laufgeschwindigkeiten haben. 

Also zwei mal unterschiedliche Thread.sleep();

Jetz läst es sich schlecht bewerkstelligen das alles in einen Thread zu setzten. 
Also starte ich für jedes Monster einen Thread, da sie sich ja alle unabhängig voneinander bewegen sollen.

Funktioniert auch schon   ...aber nur bis maximal 8 Monster. Dannach kann ich das Spielfeld auf dem sie sich bewegen nicht mehr im Fenster bewegen. Also meine Spielfigur bewegt sich nicht mehr   :cry:


----------



## Leroy42 (12. Jan 2008)

Titanpharao hat gesagt.:
			
		

> ...aber nur bis maximal 8 Monster. Dannach kann ich das Spielfeld auf dem sie sich bewegen nicht mehr im Fenster bewegen. Also meine Spielfigur bewegt sich nicht mehr   :cry:



Wobei dass sicherlich nichts mit deine 8 _gethreadeten Monstern_ zu tun hat.
Du machst da 100%-ig was anderes falsch!


----------



## Titanpharao (12. Jan 2008)

Was dann? Es ist aber echt bei 8 bei 9 gehts nicht mehr bei 8 schon.
mach das in etwa so...

```
switch (r) {
			case 0:spieler.xpos++;break;
			case 1:spieler.ypos++;break;
			case 2:spieler.xpos--;break;
			case 3:spieler.ypos--;break;
			default:break;
			}		
        	System.out.println(r);
			move=new Task_Move(r);
			move.execute();
		}
```

Den neuen Thread zum laufen wird beblockt..er kommt da nicht rein merke ich. Auf Tastarur usw reagiert er wunderbar. Muss man sowas wie "priority" setzten?


----------



## Leroy42 (12. Jan 2008)

Titanpharao hat gesagt.:
			
		

> Muss man sowas wie "priority" setzten?



Nein! Du darfst nur nicht den EDT blockieren; wie sieht denn
dein thread-code aus?


----------



## Titanpharao (12. Jan 2008)

Der fürn Spieler...


```
class Task_Move extends SwingWorker<Void, Void> {
    	int r;
    	public Task_Move(int r){
    		this.r=r;
    	}    	
        @Override
        public Void doInBackground() {
        	run=false;
        	for(int i=1;i<9;++i){
            	try {Thread.sleep(45);}
            	catch (Exception e) {}
            	switch (r) {
				case 0: panel_area.setBounds( -(areax-4)*64+(-8*i), -(areay-4)*64, xhigh, yhigh);
						switch (i) {
						case 2:player.setIcon(new ImageIcon(playerimage.getSubimage(64, 64, 64, 64)));break;
						case 4:player.setIcon(new ImageIcon(playerimage.getSubimage(0, 64, 64, 64)));break;
						case 6:player.setIcon(new ImageIcon(playerimage.getSubimage(64, 64, 64, 64)));break;
						case 8:player.setIcon(new ImageIcon(playerimage.getSubimage(0, 64, 64, 64)));break;
						default:break;
						}
						break;				
				case 1: panel_area.setBounds( -(areax-4)*64, -(areay-4)*64+(-8*i), xhigh, yhigh);
						switch (i) {
						case 2:player.setIcon(new ImageIcon(playerimage.getSubimage(64, 128, 64, 64)));break;
						case 4:player.setIcon(new ImageIcon(playerimage.getSubimage(0, 128, 64, 64)));break;
						case 6:player.setIcon(new ImageIcon(playerimage.getSubimage(64, 128, 64, 64)));break;
						case 8:player.setIcon(new ImageIcon(playerimage.getSubimage(0, 128, 64, 64)));break;
						default:break;
						}
						break;	
				case 2: panel_area.setBounds( -(areax-4)*64+(8*i), -(areay-4)*64, xhigh, yhigh);
						switch (i) {
						case 2:player.setIcon(new ImageIcon(playerimage.getSubimage(64, 192, 64, 64)));break;
						case 4:player.setIcon(new ImageIcon(playerimage.getSubimage(0, 192, 64, 64)));break;
						case 6:player.setIcon(new ImageIcon(playerimage.getSubimage(64, 192, 64, 64)));break;
						case 8:player.setIcon(new ImageIcon(playerimage.getSubimage(0, 192, 64, 64)));break;
						default:break;
						}
						break;	
				case 3: panel_area.setBounds( -(areax-4)*64, -(areay-4)*64+(8*i), xhigh, yhigh);
						switch (i) {
						case 2:player.setIcon(new ImageIcon(playerimage.getSubimage(64, 0, 64, 64)));break;
						case 4:player.setIcon(new ImageIcon(playerimage.getSubimage(0, 0, 64, 64)));break;
						case 6:player.setIcon(new ImageIcon(playerimage.getSubimage(64, 0, 64, 64)));break;
						case 8:player.setIcon(new ImageIcon(playerimage.getSubimage(0, 0 , 64, 64)));break;
						default:break;
						}
						break;	
				default:break;
				}
            	repaint();            	
        	}
        	return null;
        }       
        
        @Override
		public void done() {
			switch (r) {
			case 0:areax++;break;
			case 1:areay++;break;
			case 2:areax--;break;
			case 3:areay--;break;
			default:break;
			}
			hud.l_xy.setText(spieler.xpos+","+spieler.ypos);
        	run=true;
        }
    }
```

So....ich habe festgestellt, das alle Threads die vor dem Monster-threads erstellt werden ausgeführt werden und die nach nicht mehr. Aber wirklich erst bei 8...


Und der vom Monster...


```
class Task_Monster extends SwingWorker<Void, Void> {
    	int mnr;
    	int laufen;
    	int richtung;
        public Task_Monster(int mnr) {
			this.mnr = mnr;
		}
		@Override
        public Void doInBackground() {
        	while(monsters.get(mnr).hp>0){
        		laufen=(int)(Math.random()*3000+1000);//TODO STUN ??        		
        		try {Thread.sleep(laufen);}
        		catch (Exception e) {}
        		richtung=(int)(Math.random()*4);
        		laufen(richtung);      			        		        			      		
        	}      	        	
        	return null;
        }
        @Override
		public void done() {
        }
```


----------



## Titanpharao (12. Jan 2008)

Nein, er führt nicht mehr als 9Threads aus...


----------



## masta // thomas (12. Jan 2008)

Auch wenn die verschiedenen Objekte unterschiedlich schnell  bewegt werden sollen, kannst du alles in einen Thread packen - du musst lediglich überprüfen, wieviel Zeit zwischen jedem Durchlauf vergangen ist.
Die ganzen new ImageIcon() machen die Sache langsam. Du solltest darüber nachdenken, die Viecher zu zeichnen, und keine Panels zu bewegen!


----------



## Titanpharao (12. Jan 2008)

Es ist dennoch besser für jedes einen Thread zu haben, weil diese noch verändert werden.
Ich glaube nicht, dass bei z.B. einen richtigen RPG die Gegner sich alle durch einen Thread bewegen.

Ich habe mal bissel was getestet. Es können immer nur 10 endlose Threads gestartet werden. Wenn ich meinen Lebenspunkte-Regenerations Thread raus schmeiße, dann geht ein Monster mehr 9 statt 8 + 1 selber laufen =10.

ja das mit dem new ImageIcon ... soll ich sonnst alle schon davor laden?

Die Viecher bewegen sich auf dem Panel. Nur wenn der Spieler sich bewegt, dann muss das Panel verschoben werden. Schließlich ist der fest auf dem Bildschirm, also muss ich die Welt unter seinen Füßen bewegen.


----------



## Titanpharao (13. Jan 2008)

Lag mal SwingWorker. Habs jetzt mit 
class bla extends Thread{}

gemacht...damit wuseln jetzt 100 Gegner auf einem Bildschirm rum   

Wüste aber gern, warum es mit SwingWorker nicht ging ...


----------



## Rock Lobster (14. Jan 2008)

Hmm also bei Spielen arbeitet man üblicherweise nicht mit so vielen Threads. Meist verwendet man einen Thread für Netzwerk- und einen für Sound-Zeug, aber das Rendern und das Updaten passiert normalerweise nacheinander im MainThread. Also für jede Figur einen eigenen Thread zu machen kann meiner Meinung nach zu mehr Problemen führen als Du Dir davon Vorteile versprichst.


----------



## tuxedo (14. Jan 2008)

Titanpharao hat gesagt.:
			
		

> ja das mit dem new ImageIcon ... soll ich sonnst alle schon davor laden?



Jupp, Bilder sollten vorher schon geladen werden. Zumindest solche die eh ständig gebraucht werden. 

- Alex


----------



## EgonOlsen (14. Jan 2008)

Du brauchst in einem Spiel für die Spiellogik EINEN Thread (außer denen, die implizit sowieso da sind wie dem EDT). In diesem Thread machst du die Berechnungen für alle deinen Spielelemente nacheinander, evtl. auch das Zeichnen selber...das kommt darauf an, ob die aktives oder passives Rendering benutzt. Es gibt genau 0 Gründe, für jedes Element einen Thread zu machen, so wie es 0 Gründe gibt, die Sounds in einem extra Thread laufen zu lassen. Wozu? Die VM garantiert dir nicht, dass die Threads so an die Reihe kommen, wie du es haben willst, du bekommst wirre Reihenfolgen, es ruckelt unvorhersehbar, du bekommst Probleme mit der Synchronisation und das Spiel läuft nicht deterministisch. Außerdem erhöhst du den Verwaltungs- und Speicheraufwand. Es erscheint auf den ersten Blick zwar eine sexy Idee zu sein, aber es ist schlichtweg unsinnig.
Mach eine Spielschleife und steuere darin die Logik zeitabhängig, tick-basiert oder sonstwie. Aber verlass dich nicht auf Threads.


----------

