JAVA stworzenie n wystapien watku podczas iteracji

0

Mam problem z tworzeniem wielokrotnym wątku.
Napisałem wątek, który tworzy kopię lokalną pliku z komputera o określonym adresie IP.
Ideą programu jest pobranie z bazy danych listy adresów IP i wywołanie/stworzenie tyle razy wątków ile adresów zostanie odnalezionych.
Nie mam pomysłu jak zdefiniować unikalne nazwy wątków przy kolejnych iteracjach:

 
for (int i = 1; i <= Integer.parseInt(resultOfQuery1[0][0]); i++) {
			MachineData[0] = resultOfQuery1[i][0];
			MachineData[1] = resultOfQuery1[i][1];
			MachineData[2] = resultOfQuery1[i][2];
			
			// jak nadać unikalne nazwy dla tworzonych wątków (np.: watek+i -> watek1, watek2, watek3, ... , watekn)
			ThreadsOfMonitoring watek = new ThreadsOfMonitoring(MachineData);
			watek.start();
		}

Proszę o pomoc

P.S. Zdecydowałem się na wątki ze względu na niezawodność odpytywań. Obawiałem się, że jeśli wywołałbym metodę n razy to jeżeli powisła by na którymś odpytaniu to wstrzymałoby to odpytywanie pozostałych urządzeń. W wątkach mam nadzieję, że wywali to najwyżej odpytywanie tylko jednego PC-ta. poza tym odpytywanie będzie chodzić dla każdego kompa w pętli czasowej (co 50 sekund).

0

Utworzyc sobie w klasie kontener watkow i dopisywac je do niego

private ArrayList<ThreadsOfMonitoring> watki = new ArrayList<ThreadsOfMonitoring>();
//[...]
//w metodzie:
ThreadsOfMonitoring watek = new ThreadsOfMonitoring(MachineData);
watki.add(watek);
watek.start();
0

@VGT, po co tworzyć klasę?
@ZibiWro, zapoznaj się ze szkieletem interfejsu Executor: http://www.baptiste-wicht.com/2010/09/java-concurrency-part-7-executors-and-thread-pools/

0

Dzięki Koziołek, fajna sprawa.

Jednak mam dalej problem. Tym razem po odczytaniu powiedzmy dwóch adresów z bazy danych w iteracji wypisuje mi je oba, jednak w utworzonych wątkach widoczny jest tylko jeden, co powoduje błąd przy odpytaniu maszyn. Poniżej kod:

 
public class MainStart {

	public static void main(String[] argv) throws Exception {
		

		String query1 = "SELECT IM_ID, IM_NAME, IM_ADDRESS FROM injectionmachine WHERE IM_Status='1'";

		String[][] resultOfQuery1 = new String[1000][3];
		resultOfQuery1 = queriesSLSdb.ActiveMachines.query(query1);

		String[] injectionMachineData = new String[3];
		ExecutorService pool = Executors.newFixedThreadPool(Integer.parseInt(resultOfQuery1[0][0]));
		
		for (int i = 1; i <= Integer.parseInt(resultOfQuery1[0][0]); i++) {
			injectionMachineData[0] = resultOfQuery1[i][0];
			injectionMachineData[1] = resultOfQuery1[i][1];
			injectionMachineData[2] = resultOfQuery1[i][2];
			System.out.println("injectionMachineData[2] "+injectionMachineData[2]); // tu wyświetla poprawnie wszystkie adresy np.:
// 192.168.5.6
// 192.168.5.7
			
			pool.execute(new ThreadsOfMonitoring(injectionMachineData));
		}
	}
}

a oto część klasy z wątkiem:

 

public class ThreadsOfMonitoring implements Runnable{

	String[] injectionMachineData;

	public ThreadsOfMonitoring(String[] injectionMachineData) {
		this.injectionMachineData = injectionMachineData;
	}

	public void run() {
		// pomiar czasu
		long start = System.currentTimeMillis();

		// dane wtryskarki ----------------------
		String idInjectionMachine = injectionMachineData[0];
		String nameInjectionMachine = injectionMachineData[1];
		String ipAddressInjectionMachine = injectionMachineData[2]; 
		System.out.println("injectionMachineData[2]: "+ injectionMachineData[2]); //  w tym miejscu wyświetla tylko jeden adres i to ten drugi
//  192.168.5.7
  1. Czy każda metoda wywoływana z wątku musi być napisana jako wątek (np. taki sam wątek tworzony jest 3-krotnie, za każdym wywołaniem odwołuje się do kolejnej metody i czy ona też musi być Runnable lub extends Thread)?
0

A zauważyłeś co ty przekazujesz do wątku, który jest reprezentowany konstruktorem ThreadsOfMonitoring(String[] injectionMachineData)?
Jeżeli sądzisz, że przekazujesz tam tablicę, to bardzo się mylisz. Tablica jest obiektem, a obiekty są przekazywane przez referencję, czyli przekazujesz w istocie wskaźnik. Oznacza to, że do wszystkich wątków przekazujesz dokładnie tę samą tablicę, a zanim każdy z wątków się utworzy, to "przekręci się" pętla: for (int i = 1; i <= Integer.parseInt(resultOfQuery1[0][0]); i++), która przypisuje kolejne wartości jej elementom. Ostatecznie elementy tej tablicy otrzymają wartość jaka odpowiada ostatniemu elementowi i stąd każdy uruchomiony wątek otrzyma te same dane.
Dlatego zawsze radzę unikać przekazywanie konstruktorom obiektów, a zamiast tego albo przekazywać wartości proste, albo jawne klony obiektów, albo unikalne obiekty stworzone celowo do przekazania ich konstruktorowi konkretnego obiektu.

Co do drugiego pytania, to absolutnie nie. Traktuj wątek jak osobny procesor. Stworzenie wątków jest jakby rozdzieleniem zadań na różne maszyny, które odtąd będą wykonywać je równolegle. To oznacza, że wszystkie inne metody choć wywołane nawet dla tego samego obiektu będą działały "gdzie indziej". Tylko dane tego obiektu będą równocześnie używane. Może to więc prowadzić do ich uszkodzeń lub zakleszczenia. Dlatego takie metody jeżeli operują na tych samych danych, to powinny mieć modyfikator synchronized lub ich sekcje krytyczne (czyli tam gdzie na danych się operuje) powinny być synchronizowane.

W Twoim wypadku wybrałeś wątki aby odseparować od siebie zadania zarówno jeżeli chodzi o dane jak i wykonanie. Dlatego każdy z nich powinien operować na swoich danych. Trzeba je tylko stworzyć lokalnymi dla każdego wątku.
Najszybsze rozwiązanie Twojego problemu, to przeniesienie String[] injectionMachineData = new String[3]; do środka pętli, na jej początek.

0

Dzięki, sprawdziłem, wszystko hula i śmiga jak miło. "Bawię" się w ogóle programowaniem od b. niedawna i jeszcze przedszkolne błędy popełniam...
Przez referencję..... wykuć na ramce monitora ;-)

0

Tyle, że te referencje to trochę inaczej działają niż w C++, tam nie da się nadpisać referencji. Javowe referencje to bardziej takie C++owe wskaźniki.

W Javie przez wartość przesyłane są tylko prymitywy, czyli: boolean, byte, short, char, int, float, long, double. Ich obiektowe odpowiedniki czyli np Boolean, Byte, Character nie są prymitywami, ale są niemutowalne, więc w zasadzie wielkich różnic w użyciu między nimi nie ma.

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