我必须在Java中实现一个Client-Server应用程序,它根据客户端文件的变化自动更新Server目录中的txt文件,用于作业(必须,因为我已经过了截止日期)
我有一个正确处理文件更改的包,但我对如何处理多个文件中的更改感到困惑。我的方法是为客户端目录中的每个文件使用单独的线程,并使用服务器目录中的相应线程来实现相同的原因。这种方法适用于单个文件,但不适用于倍数。
下面的代码在客户端,并调用文件的线程的checkfilestate方法来处理更新。
while(true){
for (Map.Entry<String, SynchronisedFile> entry : fileList.entrySet()) {
try {
System.err.println("SyncTest: calling fromFile.CheckFileState()");
sstt.start();
entry.getValue().CheckFileState();
} catch (IOException e) {
e.printStackTrace();
System.exit(-1);
} catch (InterruptedException e) {
e.printStackTrace();
System.exit(-1);
}
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
e.printStackTrace();
System.exit(-1);
}
}
在服务器端,如果我使用以下命令启动单个线程:
Thread sstt = new Thread(new SyncThreadServer(sfileList.entrySet().iterator().next().getValue(),clientSocket));
sstt.start();
它按预期工作。但是,如果我使用以下命令同时启动服务器端线程(其中包含从输入流解码Json消息的方法):
for (Map.Entry<String, SynchronisedFile> entry : sfileList.entrySet())
{
Thread sstt = new Thread(new SyncThreadServer(entry.getValue(),clientSocket));
sstt.setName(entry.getKey());
}
其他文件的线程开始从输入流中读取用于其他线程的JSON消息。我希望能够阻止服务器端循环启动下一个线程,至少在一个文件/线程的checkFile方法完成之前。但是在初始阶段,当所有踏板同时运行时,我仍然可能遇到问题。在这种情况下如何处理多个线程的任何解决方案? (所有线程都使用单个插槽)。
编辑:据我所知,这与同步有关。服务器上其他文件的线程在第一个线程甚至完成处理对其有意义的输入之前访问输入流。这是下面的服务器线程的代码。我需要以某种方式阻止其他线程在第一个线程完成使用之前访问输入流。任何帮助将非常感激。感谢。
public class SyncThreadServer implements Runnable {
SynchronisedFile toFile; // this would be on the Server //Is an instance of the syncfile class, should be able to proc insts
Socket clientSocket;
public SyncThreadServer(SynchronisedFile tf, Socket aClientSocket){
toFile=tf;
clientSocket = aClientSocket;
}
@Override
public void run() {
Instruction inst = null;
InstructionFactory instFact=new InstructionFactory();
while(true){
{
try{
DataInputStream in = new DataInputStream(clientSocket.getInputStream());
DataOutputStream out = new DataOutputStream(clientSocket.getOutputStream());
String smsg = in.readUTF();
Instruction receivedInst = instFact.FromJSON(smsg);
System.err.println(smsg);
// The Server processes the instruction
toFile.ProcessInstruction(receivedInst);
//if(receivedInst.Type().equals("EndUpdate")){
// out.writeUTF("NEXT"); //TODO: Change to Json
// out.flush();}
//else
//{
out.writeUTF("GO"); //TODO: Change to Json
out.flush();
}
//}
catch (IOException e) {
e.printStackTrace();
System.exit(-1); // just die at the first sign of trouble
} catch (BlockUnavailableException e) {
// The server does not have the bytes referred to by the block hash.
try {
DataOutputStream out2 = new DataOutputStream(clientSocket.getOutputStream());
DataInputStream in2 = new DataInputStream(clientSocket.getInputStream());
out2.writeUTF("NGO"); //TODO: Change to Json
out2.flush();
String msg2 = in2.readUTF();
Instruction receivedInst2 = instFact.FromJSON(msg2);
toFile.ProcessInstruction(receivedInst2);
if(receivedInst2.Type().equals("EndUpdate")){
out2.writeUTF("NEXT"); //TODO: Change to Json
out2.flush();}
else
{
out2.writeUTF("GO"); //TODO: Change to Json
out2.flush();
}
} catch (IOException e1) {
e1.printStackTrace();
System.exit(-1);
} catch (BlockUnavailableException e1) {
assert(false); // a NewBlockInstruction can never throw this exception
}
}
// } //And here
}
}
}