Wątki - symulacja chatu

0

Witam,
napisałem prostą symulację chata:

  1. Server, prototyp serwera, w tej klasie tworzę Userów, oraz gromadzę wysyłane wiadomości;
  2. User, prototyp użytkownika, tutaj odbieram wiadomości z serwera;
  3. GenerateMessages, tutaj generuję wiadomości, które "na niby" są wysyłane przez Userów;
 
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;


public class Main {
	public static void main(String args[]) {
		Server s = new Server();
		s.start();
	}
}

class Server {
	List<User> users;
	Queue<String> messages;
	int licznik;
	
	public Server() {
		users = new ArrayList<User>();
		messages = new LinkedList<String>();
		licznik = 0;
	}
	
	public void start() {
		Thread g = new Thread(new GenerateMessages(this));
		users.add((new User(this, "JAN")));
		users.add((new User(this, "WOJCIECH")));
		
		g.start();
		new Thread(users.get(0)).start();
		new Thread(users.get(1)).start();
	}
	
}

class User implements Runnable {
	Server server;
	String name;
	boolean status;

	public User (Server server, String name) {
		this.server = server;
		this.name = name;
		this.status = false;
	}
	
	public void run() {
		try {
			while (true) {
				if (server.messages.isEmpty()) {
					System.out.println(name + ": Brak nowej wiadomości");
				}
				else {
					System.out.println(name + ": " + server.messages.poll());
				}
				Thread.sleep(1000);
			}
		} catch (Exception e) {}
	}
}

class GenerateMessages implements Runnable {
	Server server;
	
	public GenerateMessages(Server server) {
		this.server = server;
	}
	
	public void run() {
		try {
			while (true) {
				System.out.println("Odbieram: " + server.licznik);
				if (server.licznik % 4 == 0) {
					server.messages.add("NOWA WIADOMOŚĆ " + server.licznik);
				}
				server.licznik++;
				Thread.sleep(1000);
			}
		} catch (Exception e) {}
	}
}

Mam problem z tym, że w przypadku pojawienia się nowej wiadomości na serwerze, trafia ona tylko do jednego użytkownika, nie wszystkich.
Ponadto, jeden wątek "zabija" inne, nie wiem dlaczego ...

0

Brakuje tutaj synchronizacji. Jeśli obydwa wątki wejdą do else'a po isEmpty, a tylko jedna wiadomość będzie w kolejce to jeden z wątków dostanie NPE i się zakończy.

Generalnie można nawet obejść się tutaj bez sychronizacji. Wystarczy zapamiętać od razu wartość z poll() i potem sprawdzać ifem czy był to null. Musiałbyś jednak użyć np ConcurrentLinkedQueue, czyli kolejki thread-safe.

"server.licznik++;" też jest podejrzane. Niesynchronizowane może powodować "memory consistency errors".

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