我必须创建多个客户端线程,每个都必须登录。我已经将user_login函数实现为synchronized,但是当我在线程的run方法中调用它时,多个线程同时访问它。我只想要一个客户端应先登录然后再登录,依此类推......
import java.io.*;
import java.rmi.NotBoundException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.Scanner;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
class Login {
private String username = ""; //username of server manager
private String password = ""; //password of server manager
private String record = "";
private boolean flag = false;
public synchronized String user_login() {
Logger logger; //Reference to Logger class is generated
Handler fileHandler;
SimpleFormatter plainText;
Scanner s;
int thread_name = 0;
try {//login details fetched from login.txt file
BufferedReader br = new BufferedReader(new FileReader("D:/JAVA/assignment1/Login.txt"));
s = new Scanner(System.in);
System.out.println("Enter your username: ");
username = s.nextLine();
System.out.println("Enter your password: ");
password = s.nextLine();
Scanner scan;
while ((record = br.readLine()) != null) { //records fetched line by line
String[] split = record.split(" ");
if (username.equals(split[0]) && password.equals(split[1])) //username and password compared with data fetched
{
System.out.println(" LOGIN SUCCESSFULL for" + thread_name);
flag = true;
logger = Logger.getLogger(Logger.class.getName());
logger.setUseParentHandlers(false);
File f = new File("D:/JAVA/assignment1/" + username + ".txt");
if (!f.exists())
f.createNewFile();
fileHandler = new FileHandler("D:/JAVA/assignment1/" + username + ".txt", true);//File for writting log is opened in append mode
plainText = new SimpleFormatter();
fileHandler.setFormatter(plainText);
logger.addHandler(fileHandler);
logger.info("User " + username + "logged in");
}
}
} catch (Exception e) {
e.printStackTrace();
}
if (flag == false) {
System.out.println("LOGIN UNSUCCESSFULL!!!! ");
System.out.println("Try again: ");
user_login(); //if login fails,user reenter his details
}
return username;
}
}
public class Client_Thread extends Thread {
static String username = ""; //username of server manager
//password of server manager
String record = "";
static String locationname;
static boolean flag = false;
Logger logger; //Reference to Logger class is generated
int thread_name = 0;
Client_Thread(int x) {
thread_name = x;
}
@Override
public void run() //client thread statrs execution
{
System.out.println(this.thread_name);
try {
Login l = new Login();
synchronized(l)
{
username = l.user_login();
}
locationname = username.substring(0, 3);
if (locationname.equals("MTL")) //checks which server's manager logged in
{
Registry reg;
reg = LocateRegistry.getRegistry(2964);
ServerInterface ms = (ServerInterface) reg.lookup("Mtl"); //looks for reference Mtl in registry for montreal server
Operations m = new Operations();
m.Operations1(ms,username); //performs the required function
//logger.info(Logger.class.getName());
} else if (locationname.equals("LVL")) {
Registry reg = LocateRegistry.getRegistry(2965);
ServerInterface ls = (ServerInterface) reg.lookup("Lvl"); //looks for reference Lvl in registry for laval server
Operations m = new Operations();
m.Operations1(ls,username);//performs the required function
} else if (locationname.equals("DDO")) {
Registry reg = LocateRegistry.getRegistry(2966);
ServerInterface ds = (ServerInterface) reg.lookup("Ddo"); //looks for reference Ddo in registry for DDO server
Operations m = new Operations();
m.Operations1(ds,username); //performs the required function
}
} catch (IOException | NotBoundException e1) {
e1.printStackTrace();
}
}
}
public class Client {
static void test_case1()
{
for(int i=0;i<2;i++)
{
Client_Thread c = new Client_Thread(i); //run the new client thread
c.start();
}
}
public static void main(String arg[]) throws RemoteException, NotBoundException {
test_case1();
}
}
输出是这样的: - 0 1 输入你的用户名: 输入您的用户名:
但我应该像: - 输入你的用户名: 输入您的密码:
答案 0 :(得分:1)
每个线程都会创建自己的Login
对象。
因此,同步无效,因为每个线程在Login
对象的不同实例上进行同步。
为了实现所需的行为,您必须仅实例化一个Login
对象并将其传递给您要使用的所有线程。