我努力實現我的服務器和客戶端線程子類(模擬)之間的完美通信。我讀了很多文章,但我想我沒有得到如何同步線程的基本概念。同步線程通信是Java - 僅使用基本構造
問題:
我的服務器接收所有三個客戶端和關閉後的請求,客戶端打印他們從服務器得到的回答。但是服務器應該首先響應客戶端,然後應該從其他線程獲取另一個請求。 你真誠的幫助將真正被讚賞。由於
下面是其中所涉及的類別:
Server.java
public class Server extends Thread {
private boolean isRunning;
private final Map < String, List <String> > content;
private final Queue <Request> requestQueue;
public Server(String name) {
super(name);
isRunning = true;
content = new HashMap < >();
generateContent();
requestQueue = new LinkedList < >();
Timer timer = new Timer();
TimerTask timerTask = new TimerTask() {
@Override public void run() {
Runner.logf("Timer : Server shutting down...%n");
isRunning = false;
timer.cancel();
}
};
timer.schedule(timerTask, 10 * 1000);
start();
}
public synchronized boolean acceptRequest(Request request) {
if (isRunning) {
try {
Field privateClient = Request.class.getDeclaredField("client");
privateClient.setAccessible(true);
Client tClient = (Client) privateClient.get(request);
requestQueue.add(request);
Runner.logf("Server accepted Request : %s\n", request.toString());
return true;
} catch (Exception e) {
e.printStackTrace();
}
}
return false;
}
@Override public void run() {
synchronized(this) {
if (requestQueue.size() == 0) {
Runner.logf("Server : Request queue is empty, waiting...\n");
try {
wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
while (requestQueue.size() != 0) {
Runner.logf("Server : Has just been notified, getting back to work...\n");
Request temp = requestQueue.poll();
try {
Field privateClient = Request.class.getDeclaredField("client");
privateClient.setAccessible(true);
Client tClient = (Client) privateClient.get(temp);
Field privateMethod = Request.class.getDeclaredField("method");
privateMethod.setAccessible(true);
String tMethod = (String) privateMethod.get(temp);
Field privateUri = Request.class.getDeclaredField("uri");
privateUri.setAccessible(true);
String tUri = (String) privateUri.get(temp);
Field privateParameter = Request.class.getDeclaredField("parameter");
privateParameter.setAccessible(true);
String tParameter = (String) privateParameter.get(temp);
List <String> tContent = content.get(tUri);
if (tContent == null && tUri.compareTo("Index") != 0) {
tUri = "404";
}
if (tMethod.compareTo("GET") == 0) {
if (tUri.compareTo("Index") == 0) {
tContent = getKeys();
tUri = "Document";
}
Reply tRep = new Reply(tUri, tContent);
tClient.acceptReply(tRep);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
private void generateContent() {
String key;
List <String> value;
key = "A";
value = new ArrayList < >();
value.add("A1");
value.add("A2");
content.put(key, value);
key = "B";
value = new ArrayList < >();
value.add("B1");
value.add("B2");
content.put(key, value);
key = "C";
value = new ArrayList < >();
value.add("C1");
value.add("C2");
content.put(key, value);
key = "D";
value = new ArrayList < >();
value.add("D1");
value.add("D2");
content.put(key, value);
}
private List <String> getKeys() {
List <String> keys = new LinkedList <String>();
for (String k: content.keySet()) {
keys.add(k);
}
return keys;
}
}
Client.java
public class Client extends Thread {
private final Server server;
private final int periodOfRequests;
private final Random random;
private boolean firstRun;
public Client(String name, double frequencyOfRequests, Server server) {
super(name);
firstRun = true;
this.server = server;
this.periodOfRequests = (int)(1000.0/frequencyOfRequests);
this.random = new Random();
start();
}
public synchronized void acceptReply(Reply reply) throws Exception {
Runner.logf("%s : Got Reply %s\n", this.getName(), reply.toString());
}
@Override public void run() {
Request req = null;
synchronized(server) {
if (firstRun) {
firstRun = false;
Request firstReq = new Request(this, "GET", "Index", "NA");
Runner.logf("%s : Sent Request %s \n", this.getName(), firstReq);
server.acceptRequest(firstReq);
server.notify();
}
do {
try {
Thread.sleep(periodOfRequests);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
req = new Request(this, "GET", "A", "NA");
Runner.logf("%s : Sent Request %s\n", this.getName(), req);
server.notify();
} while (server.acceptRequest(req));
}
}
}
Runner.java
public class Runner
{
private static final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss.SSS ") ;
public static synchronized void logf (String format , Object ... args)
{
System.out.print (sdf.format(new Date())) ;
System.out.printf(format , args ) ;
}
public static void main (String[] args)
{
if (args.length == 0) { args = new String [] { "1" , "2" , "0.5" } ; }
Server server = new Server("Server ") ;
for (int i = 0 ; i < args.length ; i++)
{
String name = String.format ("Client%02d" , i+1) ;
double frequency = Double.parseDouble(args[i] ) ;
new Client(name , frequency , server) ;
}
}
}
電流輸出:
04:40:23.522 Server : Request queue is empty, waiting...
04:40:23.522 Client01 : Sent Request [Client01:GET:Index:NA]
04:40:23.522 Server accepted Request : [Client01:GET:Index:NA]
04:40:24.522 Client01 : Sent Request [Client01:GET:A:NA]
04:40:24.523 Server accepted Request : [Client01:GET:A:NA]
04:40:25.525 Client01 : Sent Request [Client01:GET:A:NA]
04:40:25.526 Server accepted Request : [Client01:GET:A:NA]......
我想達到的目標:
07:12:18.688 Server : Request queue is empty, waiting...
07:12:19.204 Client02 : Sent request [Client02:Get:Index:NA]
07:12:19.204 Server : Has just been notified, getting back to work...
07:12:19.204 Server : Request [Client02:Get:Index:NA] is VALID, handling...
07:12:19.204 Client02 : Got reply [Index:A,B,C,D]
07:12:19.204 Server : Request queue is empty, waiting...
怎麼了格式化?我看不懂這個.. – shmosel
@shmosel我剛剛用適當的格式更新了這個問題。 – user3057437