Thread przestaje dzialac

0

witam,
jestem totalnym laikiem jesli chodzi o Java,
ale potrzebuje nauczyc sie paru podstaw.

mam problem z Thread.

tworze gre, w ktorej np. niektore elementy beda sie przesuwac - gdy otrzymaja jakis wektor.
rozumiem ze do tego m.in sluzy Thread?

potrzebuje po prostu aby jakas funkcja byla wykonywana np. 10 razy w ciagu sekundy.
w tej funkcji sprawdzam wszystkie mozliwe obiekty, i jesli jakis obiekt ma zadany wektor - to obiekt ten przesuwam.

public void run()
	{	
		int count = 0;
		
		while (timeEventsRunning)
		{
			 
					ArrayList<MapTileItem> gravityWalls = currGame.getGravityWalls();
					
					
					if (gravityWalls != null){
						
						for (int b = 0; b < gravityWalls.size(); b++)
						{
							MapTileItem bomb = (MapTileItem) gravityWalls.get(b);
						
							if (bomb.isFalling()){

								boomb.y++;
                                                        }


						}
					}
					
			
			
			// Sleep a bit
			try
			{ 
				Thread.sleep(100); 
			}
			catch(InterruptedException e)
			{
				// Halt this thread
				extension.trace("BattleFarm extension was halted");
			}	
						
		}			
			
		}
		 

powyzszy kod wykonuje sie tylko jeden raz.
ale jesli usune linijke warunek isFalling() i zostawie:

	for (int b = 0; b < gravityWalls.size(); b++)
						{
							MapTileItem bomb = (MapTileItem) gravityWalls.get(b);
						
							boomb.y++;
                                                       


						}

to funkcja ta dziala poprawnie - tzn wykonuje sie wielokrotnie.

czegos nie rozumiem? :)

0

Na oko taka sytuacja jak mówisz może mieć miejsce, gdy
bomb.isFalling()
zrzuca wyjątek. Wątek kończy tutaj swoje działanie, gdy timeEventsRunning = false.

0

juz znalazlem blad, sadzilem ze kod

 
private boolean falling;

od razu ustawi mi zmienna na false

0

Jeszcze nie znalazłeś błędu.

private boolean falling;

ustawi wartość zmiennej falling na false.

0

no ok, ale gdy mialem:

 
public class MapTileItem {
	
	// gravity wll
	public Boolean falling;


	public boolean isFalling() {
		
		return falling;
	}

}

to przerywalo mi Thread,

gdy zmienilem na

 
public class MapTileItem {
	
	// gravity wll
	public Boolean falling = false;


	public boolean isFalling() {
		
		return falling;
	}

}

to dziala ok :)

tyle ze....

gdy zrestartuje app, to znow przerywa mi Thread....

0

Problem najprawdopodobniej leży w tej linijce:
public Boolean falling = false;

Ponieważ używasz obiektu klasy Boolean - klasy opakowującą typ boolean, zmień na public boolean falling i wtedy przetestuj.

0

niestety bez zmian

0

Jeśli wiesz tak mało o Javie, że nie odróżniasz boolean od Boolean, to nie pisz jeszcze programów wielowątkowych.

0

ale dla czego nie sprawdzic wartosc timeEventsRunning?
jak timeEventsRunning == false , to i Thread przestaje dzialac..

0

Daj cały kod.

0

Podstawowa zasada - jesli masz zmienne ktore sa czytane przez 2 watki, musza one byc volotile, lub dostep do nich musi byc za pomoca metod synchronized. U Ciebie nie ma zadnego z tych warunkow.
To ze raz dziala a raz nie to typowe dla problemow zwiazanych z wielowatkowoscia. Ba, wiecej - mozesz wkleic tutaj kod, a ktos Ci powie ze dziala i nie wie o co chodzi. Wynika to z tego ze np. optymalizacja odczytu zmiennych dla JVM serwerowych oraz klienckich sa rozne (takie Twoje isFalling moze dla klienckich nie byc optymalizowane, czyli bedzie dzialac jak chcesz, a na 64 bit linuksie JVM bedzie juz dokonywac agresywnych optymalizacji, przez ktore nie zadziala - volatile je wylacza dla tej zmiennej).

0

boolean wg. specyfikacji jest operacją atomową i nie wymaga synchronizacji. Z drugiej strony w pakiecie wielowątkowości wprowadzono AtomicBoolean - z jakiegoś powodu go wprowadzili więć może faktycznie dobrze by było użyć tego typu.

0

To akurat nie ma nic do atomowosci operacji, a do 'widocznosci' operacji przypisania przez wiele watkow. Tu chodzi o Java Memory Model, i radze Ci o nim poczytac - na IBM developers works jest swietny artykul na ten temat. A tu pierwszy lepszy artykul na ten temat: http://www.javamex.com/tutorials/synchronization_volatile.shtml
Do rzeczy i w skrocie - watek moze sobie zcachowac taka zmienna, i nie czytac tego co zapisal inny watek do pamieci glownej, co jest bledne, bo wartosci moga byc inne (jeden watek zapisze true, a stary czyta nadal zcachowany false, itp itd). Ten problem dotyczy kazdego typu danych, czy to boolean, czy referencja. Volotile temu zapobiega, tzn. wymusza na JVM i optymalizatorze, aby takie zmienne zawsze byly 'flushowane' przy zapisie, oraz czytane przez JVM bezposrednio z main mem, a nie z cachu danego watku. Uzywaie metody synchronized ma podobne wlasciwosci od Javy 5.

Przypisywanie boolean jest atomowe, tutaj masz racje i nie podlega to watpliwosci. Jednak nie w tym rzecz.

AtomicBoolean ma inne zadania - przede wszystkim daje metody typu getAndSet, compareAndSet ktore sa atomowe - tutaj wykonywane sa 2 operacje (pobieranie i ustawienie nowej wartosci, porownanie i ew. ustawienie nowej wartosci) ktore sa atomowe ale nie uzywaja bloku synchronized, lecz busy waitow i innej magii. Gdy ta funkcjonalnosc nie jest potrzebna to nie ma sensu tego uzywac.

0

Co do volatile to masz rację - trochę się zasugerowałem atomowością a nie brałem pod uwagę sposobu odczytu zmiennej w wątku.
Ale wydawało mi się że AtomicBoolean i inne tego typu rozwiązują problem poprzez synchronizację w swoich bebechach. Zaraz zobaczę co tam jest w środku:)

1 użytkowników online, w tym zalogowanych: 0, gości: 1