修改并访问线程类之外的值

时间:2017-10-17 12:10:32

标签: java multithreading oop arraylist

我是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类中删除它们?

3 个答案:

答案 0 :(得分:1)

您似乎使用ArrayList作为队列:您最后添加,并从头开始删除。因此,使用Queue界面会更好。多线程应用程序的典型队列实现是ArrayBlockingQueue。使用它而不是ArrayList

似乎你的一个线程试图在另一个线程写入之前从你的arraylist中读取一个值。使用ArrayBlockingQueue,读取线程将等待另一个线程写入值。

答案 1 :(得分:0)

  1. ArrayList更改为CopyOnWriteArrayList。它是线程安全的。如果您正在使用线程,请考虑使用synchronize块,来自java.util.concurrent的线程安全类或来自Guava库的线程安全集合。

  2. 此外,如果您使用的是线程,请考虑不使用静态字段。

  3. 如果您希望一个线程提供一些值,而另一个线程要检索它们,请考虑将List<>更改为其他集合,例如StackQueue

    < / LI>
  4. 为了更清晰的代码,尝试利用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");
}