Java 简单并发服务器
Java Simple Concurrent Server
我必须设计一个简单的服务器来接收来自多个节点的消息并将它们存储在消息存储库中。
服务器代码是:
public class CommunicationServer implements Runnable {
private List<String> messages;
private MessageRepository messageRepository;
private boolean serverBusy;
public CommunicationServer() {
messages = new ArrayList<String>();
messageRepository = new MessageRepository();
serverBusy = false;
}
@Override
public void run() {
try {
while (!Thread.interrupted()) {
synchronized (this) {
if (messages.size() > 10) {
serverBusy = true;
addMessageToRepository();
notifyAll();
}
else {
serverBusy = false;
wait();
}
}
}
}
catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
public synchronized void receiveMessage(String message) {
if (messages.size() < 10) {
messages.add(message);
}
}
private void addMessageToRepository() {
if (messages.size() != 0) {
messageRepository.addMessage(messages.remove(0));
}
}
public void showMessageRepository() {
messageRepository.showStoredMessages();
}
public synchronized boolean isServerBusy() {
return serverBusy;
}
}
节点的代码是:
public class Node implements Runnable {
private static final String CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVXYZ0123456789";
private static final int MESSAGE_LENGHT = 5;
private Random random = new Random();
private CommunicationServer communicationServer;
public Node(CommunicationServer communicationServer) {
this.communicationServer = communicationServer;
}
@Override
public void run() {
try {
while (!Thread.interrupted()) {
while (communicationServer.isServerBusy()) {
wait();
}
communicationServer.receiveMessage(generateRandomString());
}
}
catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
private String generateRandomString() {
StringBuffer randomMessage = new StringBuffer();
for (int i = 0; i < MESSAGE_LENGHT; i++) {
randomMessage.append(CHARACTERS.charAt(random.nextInt(51)));
}
return randomMessage.toString();
}
}
在 main 中,我只为服务器创建一个线程,为节点创建 5 个线程,并让它们 运行 一段时间。服务器休眠直到它收到 10 条消息,之后它必须醒来处理消息。问题是我不知道在哪里调用 notifyAll() 来唤醒负责服务器的线程。
制作 CommunicationServer implements Runnable
并没有真正意义,并暴露了您的基本误解:您将流程(服务器、客户端)中的 参与者 标识为 线程。线程不是演员;线程是执行 actor 代码的地方。
因此,当您在 CommunicationServer
中说 wait()
时,您不会让 服务器 等待消息;你让那个特定的 thread 在服务器对象上等待作为它的监视器。同样,那你说notifyAll()
,你就不是"notifying all servers";您正在通知等待该特定监视器的所有线程。它应该是客户端中的一些代码通知当前正在等待服务器监视器的线程,以及服务器中的一些代码通知那些在客户端监视器上等待的线程。
根据一般经验,当您发现自己在同一个同步块中同时使用 wait()
和 notify()
时,您可以非常确定您的逻辑有问题。
我必须设计一个简单的服务器来接收来自多个节点的消息并将它们存储在消息存储库中。
服务器代码是:
public class CommunicationServer implements Runnable {
private List<String> messages;
private MessageRepository messageRepository;
private boolean serverBusy;
public CommunicationServer() {
messages = new ArrayList<String>();
messageRepository = new MessageRepository();
serverBusy = false;
}
@Override
public void run() {
try {
while (!Thread.interrupted()) {
synchronized (this) {
if (messages.size() > 10) {
serverBusy = true;
addMessageToRepository();
notifyAll();
}
else {
serverBusy = false;
wait();
}
}
}
}
catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
public synchronized void receiveMessage(String message) {
if (messages.size() < 10) {
messages.add(message);
}
}
private void addMessageToRepository() {
if (messages.size() != 0) {
messageRepository.addMessage(messages.remove(0));
}
}
public void showMessageRepository() {
messageRepository.showStoredMessages();
}
public synchronized boolean isServerBusy() {
return serverBusy;
}
}
节点的代码是:
public class Node implements Runnable {
private static final String CHARACTERS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVXYZ0123456789";
private static final int MESSAGE_LENGHT = 5;
private Random random = new Random();
private CommunicationServer communicationServer;
public Node(CommunicationServer communicationServer) {
this.communicationServer = communicationServer;
}
@Override
public void run() {
try {
while (!Thread.interrupted()) {
while (communicationServer.isServerBusy()) {
wait();
}
communicationServer.receiveMessage(generateRandomString());
}
}
catch (InterruptedException e) {
System.out.println(e.getMessage());
}
}
private String generateRandomString() {
StringBuffer randomMessage = new StringBuffer();
for (int i = 0; i < MESSAGE_LENGHT; i++) {
randomMessage.append(CHARACTERS.charAt(random.nextInt(51)));
}
return randomMessage.toString();
}
}
在 main 中,我只为服务器创建一个线程,为节点创建 5 个线程,并让它们 运行 一段时间。服务器休眠直到它收到 10 条消息,之后它必须醒来处理消息。问题是我不知道在哪里调用 notifyAll() 来唤醒负责服务器的线程。
制作 CommunicationServer implements Runnable
并没有真正意义,并暴露了您的基本误解:您将流程(服务器、客户端)中的 参与者 标识为 线程。线程不是演员;线程是执行 actor 代码的地方。
因此,当您在 CommunicationServer
中说 wait()
时,您不会让 服务器 等待消息;你让那个特定的 thread 在服务器对象上等待作为它的监视器。同样,那你说notifyAll()
,你就不是"notifying all servers";您正在通知等待该特定监视器的所有线程。它应该是客户端中的一些代码通知当前正在等待服务器监视器的线程,以及服务器中的一些代码通知那些在客户端监视器上等待的线程。
根据一般经验,当您发现自己在同一个同步块中同时使用 wait()
和 notify()
时,您可以非常确定您的逻辑有问题。