我是OOP的新手,特别是在Java中。因此,我很难从两个类中访问和删除ArrayList中的值。
我有一个 Counter 类,其中我只有一个ArrayList,我必须从两个不同的类中调用它。
public class Counter12 {
public static ArrayList<String> clientsStorage = new ArrayList<String>();
}
班级 Server12
public class Server12 {
//public static int counter = 0;
public static void main(String[] argv) throws Exception {
//Create a server socket, bounds to a specified port
ServerSocket serverSocket = new ServerSocket(5016);
System.out.println("Server started");
//int counter = 0;
//ArrayList<String> clientsStorage = new ArrayList<String>();
while (true) {
//counter++;
Socket serverClient = serverSocket.accept(); //Wait for client to connect
ServerClientThread sct = new ServerClientThread(serverClient);
sct.start();
}
}
Class ServerClientThread 是一个Thread类,我在ArrayList中添加了一些值
public class ServerClientThread extends Thread{
Socket serverClient;
//int counter;
//int counter = 0;
ServerClientThread(Socket inSocket) {
serverClient = inSocket;
//clientNo = counter;
}
private volatile ArrayBlockingQueue<String> clientsStorage = new ArrayBlockingQueue<String>(10);
//ArrayList<String> clientsStorage = new ArrayList<String>();
public void run(){
//counter++;
try {
ObjectInputStream inputValues = new ObjectInputStream(serverClient.getInputStream());
Student12 received = (Student12) inputValues.readObject();
if (received.getName().equals("Wrong!")) {
//represent object to a text-output stream
//System.out.println("Clients connected: " + clientNo);
PrintWriter output = new PrintWriter(serverClient.getOutputStream(), true);
output.println("Wrong typed value.Try again!");
output.println("Name: Johny Domino Domino");
output.println("Age: 27");
output.println("Mark: 2");
output.println("Email: johny_domino@gmx.com");
// output.println("Clients connected: " + clientNo);
inputValues.close();
output.close();
//serverClient.close();
}
else {
Counter12.clientsStorage.add(received.getName());
int clientsNumber = Counter12.clientsStorage.size();
System.out.println("Clients: " + clientsNumber);
System.out.println("Client accepted: " + received.getName());
PrintWriter output = new PrintWriter(serverClient.getOutputStream(), true);
output.println("Student " + received.getName() + received.getEmail() + " has been received");
output.println("Clients: " + clientsNumber);
inputValues.close();
output.close();
//serverClient.close();
}
} catch (Exception e) {
// TODO: handle exception
}
}
}
在客户端类中,我应该从ArrayList中删除一些值,但我不能,因为程序显示我的ArrayList是空的
private static final long serialVersionUID = 7526472295622776147L;
//Creating fields, labels and area using JFrame class
JLabel labelName;
JLabel labelAge;
JLabel labelMark;
JLabel labelEmail;
JTextField txtFieldName;
JTextField txtFieldAge;
JTextField txtFieldMark;
JTextField txtFieldEmail;
JButton btnProcess;
JButton btnAddClient;
JButton btnLeave;
JButton btnExit;
JTextArea txtArea;
public Client12() {
//Set parameters
this.setTitle("Simple Sample");
this.setSize(420, 300);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
getContentPane().setLayout(null);
labelName = new JLabel("Full Name: ");
labelName.setBounds(10, 10, 120, 21);
add(labelName);
txtFieldName = new JTextField();
txtFieldName.setBounds(105, 10, 120, 21);
add(txtFieldName);
labelAge = new JLabel("Age: ");
labelAge.setBounds(10, 35, 120, 21);
add(labelAge);
txtFieldAge = new JTextField();
txtFieldAge.setBounds(105, 35, 120, 21);
add(txtFieldAge);
labelMark = new JLabel("Mark: ");
labelMark.setBounds(10, 60, 120, 21);
add(labelMark);
txtFieldMark = new JTextField();
txtFieldMark.setBounds(105, 60, 120, 21);
add(txtFieldMark);
labelEmail = new JLabel("Email: ");
labelEmail.setBounds(10, 85, 120, 21);
add(labelEmail);
txtFieldEmail = new JTextField();
txtFieldEmail.setBounds(105, 85, 120, 21);
add(txtFieldEmail);
btnProcess = new JButton("Process");
btnProcess.setBounds(250, 40, 120, 21);
btnProcess.addActionListener(this);
add(btnProcess);
btnAddClient = new JButton("Add Client");
btnAddClient.setBounds(250, 70, 120, 21);
btnAddClient.addActionListener(this);
add(btnAddClient);
btnLeave = new JButton("Client Leave");
btnLeave.setBounds(250, 100, 120, 21);
btnLeave.addActionListener(this);
add(btnLeave);
btnExit = new JButton("Exit");
btnExit.setBounds(250, 130, 120, 21);
btnExit.addActionListener(this);
add(btnExit);
txtArea = new JTextArea();
txtArea.setBounds(10, 120, 385, 150);
txtArea.setLineWrap(true);
txtArea.setWrapStyleWord(true);
add(txtArea);
this.setVisible(true);
}
public static void main(String[] args){
new Client12();
}
@Override
public void actionPerformed(ActionEvent event) {
if (event.getSource().equals(btnProcess)) {
try {
processInformation();
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
}
else if (event.getSource().equals(btnAddClient)){
new Client12();
}
else if (event.getSource().equals(btnLeave)){
Counter12.clientsStorage.remove(0);
System.out.println("Clients: " + Counter12.clientsStorage.size());
setVisible(false);
dispose(); //Destroy the JFrame object.
}
else if (event.getSource().equals(btnExit)){
dispose();
System.exit(0);
}
}
//Method that process input information
public void processInformation() throws UnknownHostException, IOException {
Socket s = new Socket("localhost", 5016);
ObjectOutputStream p = new ObjectOutputStream(s.getOutputStream());
String name = txtFieldName.getText();
String markStr = txtFieldMark.getText();
String ageStr = txtFieldAge.getText();
String email = txtFieldEmail.getText();
//Checks if the user entered a properly formatted name, mark, age and email
//RegEx name
String patternName = ("^[A-Z]+[a-z]+\\s[A-Z]+[a-z]+\\s[A-Z]+[a-z]+$");
Pattern patternCompileName = Pattern.compile(patternName);
Matcher matcherName = patternCompileName.matcher(name);
//RegEx mark
String patternMark = ("^[0-6]$");
Pattern patternCompileMark = Pattern.compile(patternMark);
Matcher matcherMark = patternCompileMark.matcher(String.valueOf(markStr));
//RegEx age
String patternAge = ("\\d");
Pattern patternCompileAge = Pattern.compile(patternAge);
Matcher matcherAge = patternCompileAge.matcher(String.valueOf(ageStr));
//RegEx email
String patternEmail = ("[A-z0-9._%+-]+@[A-z0-9.-]+\\.[A-z]{2,5}");
Pattern patternCompileEmail = Pattern.compile(patternEmail);
Matcher matcherEmail = patternCompileEmail.matcher(email);
int mark = 0;
int age = 0;
//Match the regular expressions
if (matcherName.find() && matcherMark.find() && matcherAge.find() && matcherEmail.find()) {
//counter++;
mark = Integer.parseInt(markStr);
age = Integer.parseInt(ageStr);
//writes primitive data of the object to an OutputStream
p.writeObject(new Student12(name, age, mark, email));
p.flush();
//Read the details from server
BufferedReader response = new BufferedReader(new InputStreamReader(
s.getInputStream()));
txtArea.setText("The server respond: " + response.readLine() + "\r\n");
txtArea.append(response.readLine() + "\r\n");
btnProcess.setEnabled(false);
p.close();
response.close();
s.close();
// txtFieldName.setText("");
//txtFieldAge.setText("");
// txtFieldMark.setText("");
// txtFieldEmail.setText("");
}
else {
//If RegEx is false, we will set name = "Wrong!"
p.writeObject(new Student12("Wrong!", age, mark, email));
p.flush();
BufferedReader response = new BufferedReader(new InputStreamReader(
s.getInputStream()));
txtArea.setText("The server respond: " + response.readLine() + "\r\n");
txtArea.append("Example: " + "\r\n");
txtArea.append(response.readLine() + "\r\n");
txtArea.append(response.readLine() + "\r\n");
txtArea.append(response.readLine() + "\r\n");
txtArea.append(response.readLine());
p.close();
response.close();
s.close();
// txtFieldName.setText("");
//txtFieldAge.setText("");
// txtFieldMark.setText("");
//txtFieldEmail.setText("");
}
}
如何从ServerClientThread类添加值并从Client类中删除它们?
答案 0 :(得分:1)
您似乎使用ArrayList作为队列:您最后添加,并从头开始删除。因此,使用Queue
界面会更好。多线程应用程序的典型队列实现是ArrayBlockingQueue。使用它而不是ArrayList
。
似乎你的一个线程试图在另一个线程写入之前从你的arraylist中读取一个值。使用ArrayBlockingQueue,读取线程将等待另一个线程写入值。
答案 1 :(得分:0)
将ArrayList
更改为CopyOnWriteArrayList
。它是线程安全的。如果您正在使用线程,请考虑使用synchronize
块,来自java.util.concurrent
的线程安全类或来自Guava库的线程安全集合。
此外,如果您使用的是线程,请考虑不使用静态字段。
如果您希望一个线程提供一些值,而另一个线程要检索它们,请考虑将List<>
更改为其他集合,例如Stack
或Queue
。
为了更清晰的代码,尝试利用java多态机制:
List<String> list = new ArrayList<>();
答案 2 :(得分:0)
我决定在按下“Leave Client”按钮后必须在“Client”类中创建一个新方法。在这个方法中,我创建了一个新的socket,outputstream,并创建了一个具有一些唯一名称的新学生,以进入Thread类中的run()方法(通过“BufferedReader”)。之后在Thread中我使用take()方法从ArrayBlockingQueue中删除队列。
客户类
else if (event.getSource().equals(btnLeave)){
if (!btnProcess.getModel().isEnabled()) {
try {
removeClient();
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
setVisible(false);
dispose(); //Destroy the JFrame object.
}
}
public void removeClient()throws UnknownHostException, IOException {
Socket s = new Socket("localhost", 5016);
ObjectOutputStream p = new ObjectOutputStream(s.getOutputStream());
p.writeObject(new Student("Remove Client!", 27, 2, "remove_client@gmx.com"));
p.flush();
BufferedReader response = new BufferedReader(new InputStreamReader(s.getInputStream()));
txtArea.setText("The server respond: " + response.readLine() + "\r\n");
}
ServerClientThread 类
else if (received.getName().equals("Remove Client!")) {
Counter.clientsStorage.take();
System.out.println("Client removed");
System.out.println("Clients: " + Counter.clientsStorage.size());
PrintWriter output = new PrintWriter(serverClient.getOutputStream(), true);
output.println("Student removed");
}