Wątki, problem z synchronizacją

Odpowiedz Nowy wątek
2011-05-14 14:06

Rejestracja: 8 lat temu

Ostatnio: 8 lat temu

0

Mam do zrobienia grę w zapałki, w skrócie chodzi o to że gracze na zmianę biorą jakąś liczbę ze stosu. Mam to zrobić na wątkach (każdy gracz to inny wątek). Problem w tym, że nie potrafię operować wątkami tak by jeden gracz czekał na drugiego. Takie musi być wywołanie całości:

public class Matches {
    public static void main(String[] args) {
        Shared t = new Shared(51, 4);
        Player tab[] = {
                new Player("Alice", t),
                new PlayerMan("The Student I", t, PlayerMan.CONSOLE),
                new Player("Mark", t),
                new PlayerMan("The Student II", t, PlayerMan.INPUT_DIALOG) };
        System.out.println("Glowny watek czeka, az ktos wygra...");
        for (int i = 0; i < tab.length; i++)
            tab[i].start();
    }
}

Napisałem takie o to klasy:

class Shared {

    public int ile = 0;
    public int ktory = 0;
    public int ileZapalek;

    public Shared(int ileZapalek, int ile) {
        this.ileZapalek = ileZapalek;
        this.ile = ile;
    }
}
import java.util.Scanner;

import javax.swing.*;

class PlayerMan extends Player {

    public static final int CONSOLE = 0;
    public static final int INPUT_DIALOG = 1;
    private int input;

    public PlayerMan(String player, Shared shared, int input) {
        super(player, shared);
        this.input = input;
    }

    protected int takeMatches(int ileZapalek) {
        int number = 0;
        do {
            if (input == INPUT_DIALOG)
                number = Integer.parseInt(JOptionPane
                        .showInputDialog("Ile bierzesz zapalek?"));
            else if (input == CONSOLE) {
                System.out.println("Ile bierzesz zapałek?");
                Scanner scan = new Scanner(System.in);
                number = Integer.parseInt(scan.next());
            }
        } while (!(number >= 0 && number <= 3));
        return number;
    }

    synchronized public void run() {
        super.run();
    }
}
class Player extends Thread {

    String player;
    Shared shared;

    public Player(String player, Shared shared) {
        this.player = player;
        this.shared = shared;
    }

    protected int takeMatches(int ileZapalek) {
        int number = ileZapalek;
        if (shared.ile > 2)
            return 1;
        if (ileZapalek % 4 == 0 || ileZapalek % 4 == 1)
            number = 1;
        else if (ileZapalek % 4 == 2)
            number = 2;
        else
            number = 3;
        return number;
    }

    synchronized public void run() {
        int number = Integer.parseInt(this.getName().substring(7));
        shared.ktory = number;
        while (true) {
            if (shared.ktory == number) {
                System.out.println("na stole jest " + shared.ileZapalek
                        + " zapalek");
                int ileZapalek = shared.ileZapalek > 3 ? takeMatches(shared.ileZapalek)
                        : shared.ileZapalek;
                System.out.println(player + " bierze " + ileZapalek);
                shared.ileZapalek -= ileZapalek;
                if (shared.ileZapalek == 0) {
                    System.out.println("Wygral: " + player);
                    System.exit(0);
                }
                try {
                    Thread.sleep((int) (Math.random() * 7000));
                } catch (InterruptedException exc) {
                    return;
                }
            }
        }

    }
}

Istotne są jedynie metody run(), reszty można nie czytać :P Jak widać gubię się w tamtym miejscu i nie mam pojęcia jak wyjść z tego. W tej chwili ten kod działa tak, że leci dowolny gracz i nie patrzy na inne, i tak sobie skacze który chce :/

Proszę o jakąkolwiek pomoc, dzięki

Pozostało 580 znaków

2011-05-14 19:42

Rejestracja: 9 lat temu

Ostatnio: 6 lat temu

0

Ten kawałek wydaje mi się podejrzany:


...
shared.ktory = number;
                while (true) {
                        if (shared.ktory == number) {
...

Skoro inne wątki śpią na mniej więcej kilka sekund, to szansa, że nastąpi kolizja jest bardzo mała.
Powinieneś inaczej sprawdzać, czy inny wątek coś robi w shared, np ustawić domyślnie shared.ktory = 0, i potem robić tak:


...
                while (true) {
                        if (shared.ktory == 0) {
                                shared.ktory = 1; // blokujesz stos dla siebie
                                ...
                                ... robisz sobie tam coś ...
                                ...
                                shared.ktory = 0; //zwalniasz stosik dla innych wątków
...

A jeżeli chcesz, aby gracze brali zapałki po kolei, to możesz robić tak, że będziesz sobie liczył ilość utworzonych obiektów typu players, każdy nowy gracz będzie dostawał numer +1 większy od ostatniego, będzie sprawdzał, czy shared.ktory = number-1, a następnie koncowo ustawial shared.ktory = number (ewentualnie 0, kiedy ostatni).

Nie wiem czy dobrze zrozumiałem problem, ale tak to widzę ;p

Pozostało 580 znaków

Odpowiedz

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