Šta je novo?

Java multithreaded problem

jddipqd

Čuven
Učlanjen(a)
17.10.2000
Poruke
2,622
Poena
725
Imam klase koje otprilike ovako izgledaju:
Kod:
public class Worker extends Thread {
	private Workshop workshop;
	Worker(Workshop workshop) {
		this.workshop = workshop;
		start();
	}
	public void run() {
		Customer current = workshop.getCustomer();
		/* Radi nešto */
		workshop.customerDone();
	}
}

public class Customer extends Thread {
	private Workshop workshop;
	Customer(Workshop workshop) {
		this.workshop = workshop;
		start();
	}
	public void run() {
		workshop.addToQueue(this);
	}
}

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
public class Workshop {
	private ConcurrentLinkedQueue<Customer> queue;
	
	Workshop() {
		queue = new ConcurrentLinkedQueue<Customer>();
	}	
	
	public int queueSize() {
		return queue.size();
	}
	
	public synchronized void addToQueue(Customer customer){
		queue.add(customer);
		notifyAll();
		try {
			wait();
		} catch (InterruptedException e) {
			throw new RuntimeException(e);
		}
	}
	public synchronized Customer getCustomer() {
		while (queueSize() == 0) {
			try {
				wait();
			} catch (InterruptedException e) {
				throw new RuntimeException(e);
			}
		}
	}
	public synchronized void customerDone() {
		notifyAll();
	}
}
Za slučaj da se prvo napravi workshop, pa worker pa customer ovo bi trebalo da radi (ako sam ja dobro shvatio kako niti funkcionišu 😉 ):
  • Worker pozove workshop.getCustomer().
  • Pošto u redu nema nikoga blokira se na workshop.
  • Customer pozove workshop.addToQueue(this) koja doda customera u red, obavesti sve workere koji čekaju na workshop i blokira customera koji ju je pozvao.
  • Kada se worker probudi workshop.queueSize() više nije 0 i worker nastavlja sa radom.

Međutim, ako je blokiran, worker se ne budi kad stigne notifyAll(), a ako nije blokiran (za slučaj da se prvo napravi customer) ne konstatuje da red više nije prazan (odnosno workshop.queueSize() i dalje vraća 0).

U čemu je ovde problem?
 
Hm, kao prvo wait() bi uvek trebalo pozivati iz while petlje... nisam bas skapirao zasto, ali baci pogled na Tartaljinu skriptu, 4 strana....

Sto se tice varijante kada prvo pravis customer, pa worker ne mora da znaci da u trenutku pravljenja workera nesto ima u redu (pretpostavljam da su to komande jedna za drugom...) posto ti u konstruktoru pozivas samo this.start() ne dodajes customera
u red, to se desava tek kad customer dobije procesorsko vreme... Znaci moguce je da ce worker dobiti cpu vreme pre customera i red ce biti przan bez obzira na to sto ju customer prvi postojao...

Probaj da workshop.addToQueue(this) dodas u konstruktor pa vidi da li workshop.queSize() i dalje vraca 0.... Ustvari nisam siguran da je pametno zaustavljati konstruktor... bolje probaj da manuelno pozoves
NekiWorkshop.addToQueue(NekiCustomer) iz maina pa tek onda napravi workera....
Bar da vidis gde zaglavljuje...

P.S. Zasto je uopste customer u ovom primeru nit?
Pogledaj i 8.2 kod Lasla slicno je
 
Nazad
Vrh Dno