如何让Java线程始终在另一个线程之前运行?

dia*_*t66 -1 java static multithreading static-members thread-safety

在我的程序中,当用户输入一个号码时,程序通过套接字将该号码发送到服务器,服务器发回与该号码匹配的数据.该数字代表服务级别.具有IncomingReader()实例作为其runnable的线程然后读取从服务器发送的内容,并将其存储为arraylist(详细信息).然后,我使用详细信息arraylist中的数据创建类MyClients的对象.我的问题是创建对象的循环在从服务器读取数据的线程运行之前运行.如何在创建对象的循环之前使从服务器读取的线程运行?代码如下:(我为了简洁而删除了GUI的代码)

public class SearchClients {

JFrame frame;
private JTextField textField;
private JTextField textField_1;
private JTextField textField_2;
private JTextField textField_3;


BufferedReader reader;
PrintWriter writer;
Socket sock;

 static ArrayList<String> details = new ArrayList<String>();

public static void main(String[] args) {
    EventQueue.invokeLater(new Runnable() {
        public void run() {
            try {
                SearchClients window = new SearchClients();
                window.frame.setVisible(true);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    });
}

public SearchClients() {
    initialize();
}

private void initialize() {

    setUpNetworking();
    Thread readerThread = new Thread(new IncomingReader());
    readerThread.start();


    JButton btnSearchByService = new JButton("Search By Service Level");

    btnSearchByService.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent arg0) {
            searchByServiceLevel();
        }
    });

}

public void searchByServiceLevel() {

    try {
        writer.println("SEARCH BY SERVICE LEVEL");
        writer.println(textField_1.getText());
        writer.flush();


    }
    catch (Exception ex) {
        ex.printStackTrace();
    }



    JPanel nameSearchPane = new JPanel(new BorderLayout());

    frame.setExtendedState(Frame.MAXIMIZED_BOTH);
    frame.setContentPane(nameSearchPane);
    frame.invalidate();
    frame.validate();

    String[] columns = {"Name", "Phone Number", "Address", "District", "County", "Village", "Installation Date", "Energy Store", "Service Level", "Account Balance", "Months Owed", "Next Payment Date"};

    ArrayList<MyClients> clientDetails = new ArrayList<MyClients>();
    for(int y = 0; y < details.size(); y++) {
        MyClients client = new MyClients();
        client.name = details.get(y);
        client.phone_number = details.get(++y);
        client.address = details.get(++y);
        client.district = details.get(++y);
        client.county = details.get(++y);
        client.village = details.get(++y);
        client.installation_date = details.get(++y);
        client.energy_store = details.get(++y);
        client.service_level = details.get(++y);
        client.next_payment_date = details.get(++y);
        client.account_balance = details.get(++y);
        client.months_owed = details.get(++y);
        clientDetails.add(client);

    }

    details.clear();

//      Check if any data was returned from the database
    if(clientDetails.isEmpty()) {
        JOptionPane.showMessageDialog(frame, "A client with that service level was not found.\n Try service level: 1, 2, 3 or 4.");

        frame.setVisible(false);
        SearchClients search = new SearchClients();
        search.frame.setVisible(true);
    }

    String[][] clients = new String[100][100];

    for(int x = 0; x < clientDetails.size(); x++) {
        clients[x][0] = clientDetails.get(x).name;
        clients[x][1] = clientDetails.get(x).phone_number;
        clients[x][2] = clientDetails.get(x).address;
        clients[x][3] = clientDetails.get(x).district;
        clients[x][4] = clientDetails.get(x).county;
        clients[x][5] = clientDetails.get(x).village;
        clients[x][6] = clientDetails.get(x).installation_date.toString();
        clients[x][7] = clientDetails.get(x).energy_store;
        clients[x][8] = clientDetails.get(x).service_level;
        clients[x][9] = clientDetails.get(x).account_balance;
        clients[x][10] = clientDetails.get(x).months_owed;
        clients[x][11] = clientDetails.get(x).next_payment_date.toString(); 

    }

    JTable table = new JTable(clients, columns);
    JScrollPane tableContainer = new JScrollPane(table);
    nameSearchPane.add(tableContainer, BorderLayout.CENTER);

}

private void setUpNetworking() {
    try {
        sock = new Socket("127.0.0.1", 5000);
        InputStreamReader streamReader = new InputStreamReader(
                sock.getInputStream());
        reader = new BufferedReader(streamReader);
        writer = new PrintWriter(sock.getOutputStream());
        System.out.println("Networking established");
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}


class IncomingReader implements Runnable {
    public void run() {
        String message;
        try {
            while ((message = reader.readLine()) != null) {
                details.add(message);

            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

class MyClients {
    String name = "";
    String phone_number = "";
    String address = "";
    String district = "";
    String county = "";
    String village = "";
    String installation_date = "";
    String energy_store = "";
    String service_level = "";
    String next_payment_date = "";
    String account_balance = "";
    String months_owed = "";
    String clientID = "";
}

}
Run Code Online (Sandbox Code Playgroud)

小智 7

为什么你将它们放在不同的线程中?

通常,如果B的执行依赖于A的执行,那么在单独的线程中使用A和B是您不需要的开销,它们实际上是顺序的.

现在已经不在了,看起来你正在尝试编写服务器.通常,您将"服务器"作为自己的应用程序运行.它会打开一个套接字,然后等待输入.在输入时,它会启动一个工作线程(以便服务器可以继续接收套接字上的连接).然后通过套接字将信息发送回调用程序.调用程序将信息发送到服务器,并"等待"直到信息返回.

所以你可能想做一些事情.

  • 你可能想让你的"线程"成为实际的不同应用程序
  • 你需要在发送线程中"等待":

    • 通信响应的某种形式的阻止
    • 一个回调对象,可以在响应时调用
    • 应用程序循环中的某些内容,用于查询响应.

作为最后的评论,你需要在线程B之前运行线程A,你的线程错误.并需要停下来看看为什么:)