Threasds + Socket

Pessoal,

Estou com um problema cruel. Estou fazendo a comunicação com dois softwares via Socket. Acontece que o primeiro cliente que se conecta no Socket funciona normalmente, já quando o segundo tenta se conectar ele não obtem sucesso. Tudo porque nessa linha do código a primeira thread do socket fica parada:

off += client.getInputStream().read(b, off, length - off);

O sistema funciona da seguinte forma: quando é gerado deploy do sistema, o mesmo inicia uma thread chamada de Server, essa thread fica esperando, via socket, algum cliente se conectar, depois de identificar o cliente e recuperar o identificador desse cliente, seta pra dentro de um map, a thread com o id do cliente (para futura recuperacao da thread), depois executa a mesma. Só que no momento que o segundo cliente tenta se conectar, o sistema todo para (literalmente). Verifiquei que é no método citado acima. Provavelmente um problema de sincronizacao de threads. Só não tenho idéia de como resolver. Peço ajuda, qualquer coisa é bem-vinda.

Segue os codigos fontes:

Server

public void run() {
		System.out.println("Waiting for client...");		
		try {						
			ServerSocket ss = new ServerSocket(port);			
			//socketClients.put(0, null);
			while (true){
				/* Gera um identificador para o atendimento, e consequentemente
				 * para a thread do socket. Para poder ser recuperado posteriormente
				 * para o envio de mensagens para o cliente.*/
				idAtendimento = factory.getAtendimentoDao().nextValue();					
				System.out.println(idAtendimento);
				SocketClient sc = new SocketClient(ss.accept(), factory, idAtendimento);				
				
				System.out.println("Client connected.");
				socketClients.put(idAtendimento, sc);
				socketClients.get(idAtendimento).run();						
			}
		} catch (IOException e) {
			e.printStackTrace();			
		}			
	}

SocketClient


public void run() {
		try {
			XMLParser parser;
			String input;
			String action;
			
			this.setDaemon(true);			
			
			while (client.isConnected()) {
				System.out.println("Run thread: " + idAtendimento);

				input = new String(safeRead(6));
				input = input.substring(1, 5);
				int len = Integer.parseInt(input);
				input = new String(safeRead(len));
...

public byte[] safeRead(int length) {
		byte[] b = new byte[length];
		try {
			int off = 0;			
			while (off < length) {
				synchronized (this.safeRead(length)) {									
					off += client.getInputStream().read(b, off, length - off);
				}
			}
		} catch (Exception e) {
			System.out.println("Falha ao recuperar I/O do cliente");
			e.printStackTrace();
		}
		return b;
	}

Obrigado.

SocketClient não é uma nova Thread. Você está chamando run() diretamente.

socketClients.get(idAtendimento).run();

Quando o correto (se se trata de uma Thread) seria:
new Thread(sc).start();

No caso de um servidor, valeria ainda a pena olhar a classe ExecutorsService do Java 5 para usar um thread pool.

Também não entendi o motivo da sincronização

synchronized (this.safeRead(length))

O objeto usado como lock não deveria ser simplesmente this? Outra coisa, não haverá exatamente um objeto desse por thread? Nesse caso, para que a sincronização?

A sincronização só é necessária quando várias threads acessam o mesmo objeto.