同步线程通信是Java的,只使用原语结构
我正在努力实现服务器和客户端线程子类(模拟)之间的完美通信。我读了很多文章,但我想我还没有掌握如何同步线程的基本概念 问题:同步线程通信是Java的,只使用原语结构,java,multithreading,concurrency,Java,Multithreading,Concurrency,我正在努力实现服务器和客户端线程子类(模拟)之间的完美通信。我读了很多文章,但我想我还没有掌握如何同步线程的基本概念 问题: 我的服务器正在接收来自所有三个客户端的请求,关闭后,客户端将打印从服务器收到的回复。但服务器应该首先响应客户机,然后从其他线程获得另一个请求。 我们将非常感谢你的帮助。谢谢 以下是所涉及的课程: Server.java public class Server extends Thread { private boolean isRunning; private final
我的服务器正在接收来自所有三个客户端的请求,关闭后,客户端将打印从服务器收到的回复。但服务器应该首先响应客户机,然后从其他线程获得另一个请求。 我们将非常感谢你的帮助。谢谢 以下是所涉及的课程:
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;
}
}
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));
}
}
}
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...
Runner.javapublic 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;
}
}
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));
}
}
}
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...
我想要实现的目标: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;
}
}
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));
}
}
}
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...
我认为您需要的是将整个
服务器的run()
方法放入一个循环中:
@Override
public void run() {
synchronized (...) {
while (isRunning) {
//
// (check the Queue...process requests)
//
}
}
}
我假设您需要为您的客户机
类执行相同的操作
现在,Server
检查队列一次,然后run
方法返回,线程死亡
此外:
- 您不应该在
线程
的实例上使用同步
/等待
/通知
/等<代码>线程
将监视器本身用于其他内容,如:
此实现使用This.wait
循环调用This.isAlive
。当线程终止时,调用此.notifyAll
方法。建议应用程序不要在线程
实例上使用等待
、通知
或通知所有
相反,创建一个对象字段,如private final object monitor=new object()代码>然后在此基础上进行同步。制作一个getter,这样您的客户机
类就可以访问它,但他们可能不需要访问它。您可能应该只放置monitor.notify()
在acceptRequest
方法中
为什么要使用反射来访问请求上的私有字段,例如请求
??只要做一个吸气剂
格式是怎么回事?我无法阅读此内容。@shmosel我刚刚用正确的格式更新了问题。我按照您的指示,耐心地解决了我的问题,现在线程可以正常通信。只是一个小问题,当服务器已经关闭并将其状态记录到控制台时,所有三个客户端都会再发送一个请求,程序不会终止。你能帮忙吗?