Я действительно не вижу необходимости.
Это школа, верно?
Если вам нужно отслеживать клиентов, у вас должно быть локальное представление каждого клиента (объект Client на вашем сервере). Он может позаботиться о том, что вам нужно сделать для конкретного клиента.
В этом случае Вы должны быть в состоянии выяснить, с какого клиента было отправлено сообщение. (используя информацию из сообщения.) Вы можете держать клиентов на карте.
Наиболее эффективным способом, вероятно, является выполнение всей обработки в главном потоке, если только то, что необходимо сделать, не может "заблокировать" ожидание внешних событий (или если некоторые вещи, которые должны произойти, могут занять много времени, а некоторые - очень короткий.)
public class Client {
public void handleMessage(Message m) {
// do stuff here.
}
}
Возможно, клиентский объект может начать новый поток в handleMessage (), если это необходимо.
Вы не должны запускать несколько потоков сервера.
Серверный поток может сделать:
while(running) {
socket.receive(DatagramPacket p);
client = figureOutClient(p);
client.handleMessage(p);
}
Если нет никаких специфических для клиента вещей, о которых нужно заботиться, просто прочитайте сообщения и обрабатывайте их по мере их поступления в одном потоке.