-1

私のプログラムでは、ユーザーが数字を入力すると、プログラムはソケットを介してその数字をサーバーに送信し、サーバーはその数字に一致するデータを送り返します。数字はサービスレベルを表します。ランナブルとして IncomingReader() インスタンスを持つスレッドは、サーバーから送信されたものを読み取り、それを arraylist(details) に保存します。次に、詳細配列リストのデータを使用してクラス 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 = "";
}

}
4

4 に答える 4

7

なぜそれらを別のスレッドに持っているのですか?

通常、B の実行が A の実行に依存している場合、A と B を別々のスレッドに置くことは必要のないオーバーヘッドであり、事実上シーケンシャルです。

サーバーを作成しようとしているようです。通常、「サーバー」は独自のアプリケーションとして実行します。ソケットを開き、入力を待ちます。入力時に、ワーカー スレッドをスピンアップします (サーバーがソケットで接続を受信し続けることができるようにするため)。そして、ソケットを介して呼び出しプログラムに情報を送り返します。呼び出し元のプログラムはサーバーに情報を送信し、情報が返ってくるまで「待機」します。

したがって、おそらくやりたいことがいくつかあります。

  • おそらく、「スレッド」を実際の異なるアプリケーションにしたいでしょう
  • 次のいずれかの方法で、送信スレッドで「待機」する必要があります。

    • 通信応答に対する何らかの形式のブロック
    • 応答時に呼び出すことができるコールバック オブジェクト
    • 応答を照会するアプリケーションループ内の何か。

最後のコメントとして、スレッド B の前にスレッド A を実行する必要があるときはいつでも、スレッド化が間違っています。そして立ち止まって理由を見る必要があります:)

于 2013-08-19T01:05:47.247 に答える
2

joinclass のメソッドを使用できますThread。スレッドが実行を完了するまで待機してから戻ります。その後、2 番目のスレッドを開始できます。

于 2013-08-19T00:57:14.487 に答える