С каждым сообщение, переменная счетчика должна быть увеличена.
Что я уже реализовал
У меня есть 2 класса. Класс ProcessPlayer и класс Main.
Код: Выделить всё
MainКласс Чтобы иметь общую переменную-счетчик, я решил использовать простой текстовый файл, который будет иметь переменную-счетчик и обе процессы будут читать значение, добавлять к сообщению, обновлять значение в файле для следующего процесса. Ниже приведен код класса Main.java.
Код: Выделить всё
public class Main {
public static void main(String[] args) throws FileNotFoundException {
System.out.println("Implementing players on different processes.\n");
Utils.createFile(); // both players on different processes will use this common file.
String classpath = Paths.get(".").toAbsolutePath().normalize().toString();
classpath = classpath + "\\src";
ProcessBuilder secondPlayerProcessBuilder = new ProcessBuilder(
"java", "-cp", classpath, "ProcessPlayer", "Player2", "5003", "5002", "false"
).inheritIO();
ProcessBuilder firstPlayerProcessBuilder = new ProcessBuilder(
"java", "-cp", classpath, "ProcessPlayer", "Player1","5002", "5003", "true"
).inheritIO();
try {
Process secondPlayerProcess = secondPlayerProcessBuilder.start();
Process firstPlayerProcess = firstPlayerProcessBuilder.start();
secondPlayerProcess.waitFor();
firstPlayerProcess.waitFor();
secondPlayerProcess.destroy();
firstPlayerProcess.destroy();
System.out.println("First player process exited with code: " + firstPlayerProcess.exitValue());
System.out.println("Second player process exited with code: " + secondPlayerProcess.exitValue());
Utils.deleteFile();
} catch (IOException | InterruptedException exception) {
exception.printStackTrace();
}
}
- Первоначально создает файл со значением счетчика, равным 0.
- Создает два процесса, в которых выполняются объекты «ProcessPlayer».
Код: Выделить всё
public class Utils {
public static void createFile() {
try {
if (new File("messageCounter.txt").createNewFile()) {
System.out.println("File Created");
PrintWriter writer = new PrintWriter(new FileWriter("messageCounter.txt"));
writer.print(0);
writer.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void deleteFile() {
boolean isDeleted = new File("messageCounter.txt").delete();
if (isDeleted) {
System.out.println("File removed!");
}
}
public static void updateCounter(int newCounter) throws IOException {
PrintWriter printWriter = new PrintWriter(new FileWriter("messageCounter.txt"));
printWriter.print(newCounter);
printWriter.close();
}
}
В частности, «updateCounter» — это метод, который будет использоваться обоими процессами во время обратной и обратной связи.
}
В частности, «updateCounter» — это метод, который будет использоваться обоими процессами во время обратной и обратной связи. p>
И, наконец, ниже я прикрепляю класс «ProcessPlayer.java».
Код: Выделить всё
public class ProcessPlayer {
int numberOfMessagesSent;
int maxMessages;
static int messageCounter = 0;
boolean isInitiator;
private String playerName;
int port;
int partnerPort;
private ProcessPlayer(ProcessPlayer.PlayerBuilder builder) {
this.numberOfMessagesSent = builder.numberOfMessagesSent;
this.maxMessages = builder.maxMessages;
this.isInitiator = builder.isInitiator;
this.playerName = builder.playerName;
this.port = builder.port;
this.partnerPort = builder.partnerPort;
}
public void start() {
new Thread(this::receiveMessage).start();
if (this.isInitiator) {
sendMessage("HelloWorld!!", true);
}
}
// read counter from file, append it to message and increment it. Update the file with incremented counter.
public void sendMessage(String message, boolean initialMessage) {
try {
Socket socket = new Socket("localhost", this.partnerPort);
PrintWriter stream = new PrintWriter(socket.getOutputStream(), true);
String senderInfo = "This message was sent from " + this.getPlayerName() + ":";
FileReader fileReader = new FileReader("messageCounter.txt");
int character;
StringBuilder counterFromFile = new StringBuilder();
while (counterFromFile.toString().isEmpty()) {
while ((character = fileReader.read()) != -1) {
counterFromFile.append((char) character);
}
}
fileReader.close();
if (numberOfMessagesSent < maxMessages) {
numberOfMessagesSent++;
if (initialMessage) {
stream.println(senderInfo + message);
}
else if (Integer.parseInt(String.valueOf(counterFromFile)) == 0) {
stream.println(senderInfo + message + counterFromFile);
Utils.updateCounter(Integer.parseInt(counterFromFile.toString()) + 1);
}
else {
stream.println(senderInfo + message + counterFromFile);
Utils.updateCounter(Integer.parseInt(counterFromFile.toString()) + 1);
}
}
} catch(Exception e) {
e.printStackTrace();
}
}
public void receiveMessage() {
try {
ServerSocket serverSocket = new ServerSocket(this.port);
while(numberOfMessagesSent < maxMessages) {
Socket s = serverSocket.accept();
BufferedReader reader = new BufferedReader(new InputStreamReader(s.getInputStream()));
String message = reader.readLine();
System.out.println(message);
message = message.substring(message.lastIndexOf(":") + 1);
if (messageCounter < maxMessages) {
sendMessage(message, false);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public String getPlayerName() {
return playerName;
}
public static class PlayerBuilder {
int numberOfMessagesSent;
int maxMessages;
boolean isInitiator;
String playerName;
int port;
int partnerPort;
public PlayerBuilder(int port, int partnerPort) {
this.numberOfMessagesSent = 0;
this.maxMessages = 10;
this.port = port;
this.partnerPort = partnerPort;
}
public ProcessPlayer.PlayerBuilder setInitiator(boolean isInitiator) {
this.isInitiator = isInitiator;
return this;
}
public ProcessPlayer.PlayerBuilder setName(String name) {
this.playerName = name;
return this;
}
public ProcessPlayer build() {
return new ProcessPlayer(this);
}
}
/**
* This method initializes a player instance with the required parameters
* (name, port, and partner's port) and starts the communication process.
* This will be one of the two processes.
* @param args - The value in args array will be passed from Main.java via ProcessBuilderObject
*/
public static void main(String[] args) {
if (args.length != 4) {
System.out.println("Usage: java Player
");
return;
}
String name = args[0];
int port = Integer.parseInt(args[1]);
int partnerPort = Integer.parseInt(args[2]);
boolean isInitiator = Boolean.parseBoolean(args[3]);
try {
ProcessPlayer player = new ProcessPlayer.PlayerBuilder(port, partnerPort)
.setInitiator(isInitiator)
.setName(name).build();
player.start();
} catch (Exception e) {
System.out.println("Exception caught");
throw e;
}
}
У меня непоследовательное поведение. Если я полностью перекомпилирую классы «Main.java» и «ProcessPlayer.java» и запущу приложение, я получу следующий результат.
Код: Выделить всё
This message was sent from Player1:HelloWorld!!
This message was sent from Player2:HelloWorld!!0
This message was sent from Player1:HelloWorld!!01
This message was sent from Player2:HelloWorld!!011
This message was sent from Player1:HelloWorld!!0112
This message was sent from Player2:HelloWorld!!01123
This message was sent from Player1:HelloWorld!!011234
This message was sent from Player2:HelloWorld!!0112345
This message was sent from Player1:HelloWorld!!01123456
This message was sent from Player2:HelloWorld!!011234567
Код: Выделить всё
This message was sent from Player1:HelloWorld!!
This message was sent from Player2:HelloWorld!!0
java.lang.NumberFormatException: For input string: ""
at
java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67)
at java.base/java.lang.Integer.parseInt(Integer.java:565)
at java.base/java.lang.Integer.parseInt(Integer.java:685)
at ProcessPlayer.sendMessage(ProcessPlayer.java:61)
at ProcessPlayer.receiveMessage(ProcessPlayer.java:85)
at java.base/java.lang.Thread.run(Thread.java:1570)
Подробнее здесь: https://stackoverflow.com/questions/786 ... -processes
Мобильная версия