Witam
Chciałbym zsynchronizować wątki tak, aby rysowały na buforze i następnie czekały aż ostatni uruchomiony wątek klasy Sprite namaluje swoją część, podmieni bufor i obudzi czekające wątki. Niestety mi to nie wyszło. Poniżej podaje kod i jezeli ktoś mogłby go poprawić byłbym wdzięczny.

class Sprite implements Runnable{
        int static nr =0;
        // wspolny bufor
    private Graphics2D buffer;
        // rozmiary pulpitu
    private int width, height;
       // panel do rysowania    
    JPanel panel;
    private Color clr;
        // do transformacji
    private Area area;
        // do wykreslania
    private Shape shape;
        // przeksztalcenie obiektu
    private AffineTransform aft;
        //liczba uruchominych obiektow klasySprite
    private count = 0;
        // przesuniecie
    private int dx, dy;
        // rozciaganie
    private double sf;
        // kat obrotu
    private double an;
        // ziarno dla generatora liczb losowych
    static private int seed = 0;

    public Sprite(Graphics2D buf, int w, int h, int cc,JPanel pa){
        buffer = buf;
        width = w;
        height = h;
        count = cc;
        panel = pa;
       
        
        Random rand = new Random(seed++);
        dx = 1+rand.nextInt(5);
        dy = 1+rand.nextInt(5);
        sf = 1+0.05*rand.nextDouble();
        an = 0.1*rand.nextDouble();
        
        clr = new Color(rand.nextInt(255), 
                        rand.nextInt(255), 
                        rand.nextInt(255), 
                        rand.nextInt(255));        
        shape = new Rectangle2D.Float(0, 0, 10, 10);
        aft = new AffineTransform();                                  
        area = new Area(shape);
    }

    public void run(){
            // przesuniecie na srodek
        aft.translate(100, 100);
        area.transform(aft);
        shape = area;
        
        while(true){
            // przygotowanie nastepnego kadru
            shape = nextFrame();
	    rysuj();
            synchronized(this){ i++;}
            if(i!= count) wait();
	    else{
		i=0;
		panel.maluj();
		notifyAll();
		
	    }
            
           
        }
    }

    protected Shape nextFrame(){
            // zapamietanie na zmiennej tymczasowej
            // aby nie przeszkadzalo w wykreslaniu
        area = new Area(area);
        aft = new AffineTransform();                                  
        Rectangle bounds = area.getBounds();
        int cx = bounds.x + bounds.width/2;
        int cy = bounds.y + bounds.height/2;
            // odbicie
        if(cx < 0 || cx > width)
            dx = -dx;
        if(cy < 0 || cy > height)
            dy = -dy;
            // zwiekszenie lub zmniejszenie
        if(bounds.height > height/3 || bounds.height < 10)
            sf = 1/sf;
            // konstrukcja przeksztalcenia
        aft.translate(cx, cy);
        aft.scale(sf, sf);
        aft.rotate(an);
        aft.translate(-cx, -cy);
        aft.translate(dx, dy);
            // przeksztalcenie obiektu
        area.transform(aft);
        return area;
    }
    
    public void rysuj(){
            // wypelnienie obiektu
        buffer.setColor(clr);
        buffer.fill(shape);
            // wykreslenie ramki
        buffer.setColor(clr.darker());
        buffer.draw(shape);
    }
} 

// funkcja podmieniajaca bufor
 public void maluj(){
        device.drawImage(image, 0, 0, null);
        buffer.clearRect(0, 0, getWidth(), getHeight());