Javaでプログラミングするのは初めてではありませんが、私はJavaプログラムでスレッドを使うのが初めてです。私は学校に通っていて、スレッドとJavaネットワーキングの章を終えました。私はクライアントのGUIをプログラミングして、ローン情報(年間金利、年数、ローン金額)をサーバーに送信していました。サーバーには独自のGUIがあり、毎月の支払い額とローンの合計支払い額が計算され、クライアントに送り返され、ユーザーに表示され、サーバーGUIが更新されます。JavaFXの異なるクラスファイル間でスレッドを使用する方法はありますか?
本は、一例として、このコードを持っています
public class Server extends Application {
/** Variables */
private TextArea textArea = new TextArea();
private double rate;
private int year;
private double loan;
public void start(Stage serverStage)
{
// Creating server GUI
Scene scene = new Scene(new ScrollPane(textArea), 400, 200);
serverStage.setTitle("Server");
serverStage.setScene(scene);
serverStage.show();
new Thread(() ->{
try
{
// create server socket
ServerSocket serverSocket = new ServerSocket(8000);
textArea.appendText("Server started at " + new Date() + "\n");
while(true)
{
// listen for a connection request
Socket socket = serverSocket.accept();
Platform.runLater(() -> {
InetAddress inetAddress = socket.getInetAddress();
textArea.appendText("Connected to " + inetAddress.getHostAddress() + " at " + new Date() + "\n");
});
// create and start a new thread for every connection
new Thread(new HandleAClient(socket)).start();
}
}
catch(IOException ex)
{
ex.printStackTrace();
}
}).start();
}
class HandleAClient implements Runnable {
private Socket socket; // A connected socket
private double rate;
private int year;
private double loan;
/** costruct a thread */
public HandleAClient(Socket socket)
{
this.socket = socket;
}
/** run a thread */
public void run(){
try
{
// create data input and output streams
DataInputStream inputFromClient = new DataInputStream(socket.getInputStream());
DataOutputStream outputToClient = new DataOutputStream(socket.getOutputStream());
// continuously serve the client
while(true) {
// read data from client
rate = inputFromClient.readDouble();
year = inputFromClient.readInt();
loan = inputFromClient.readDouble();
// calculate monthly payment of loan and total payment
outputToClient.writeDouble(calculateMonthlyPayment(rate, year, loan));
outputToClient.writeDouble(calculateTotalPayment(rate, year, loan));
Platform.runLater(() -> {
textArea.appendText("The rate is : " + rate + "\n");
textArea.appendText("The number of years is: " + year + "\n");
textArea.appendText("Loan amount is: " + loan + "\n\n");});
}
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
// calculateMonthlyPayment method calculates the monthly payment of a loan given
// the required information
public double calculateMonthlyPayment(double interestRate, int years, double loanAmt)
{
double monthlyRate;
int termInMonths;
double monthlyPayment;
// Convert the interest rate to a decimal
interestRate = interestRate/100;
// convert annual interest rate to monthly interest rate
monthlyRate = interestRate/12;
// calculate the term in months which is years * 12
termInMonths = years * 12;
monthlyPayment = (loanAmt*monthlyRate)/(1-Math.pow(1+monthlyRate, -termInMonths));
return monthlyPayment;
}
// method that calculates and returns the total payment of the loan
public double calculateTotalPayment(double rate, int year, double loan)
{
double totalPayment;
double monthlyPay;
monthlyPay = calculateMonthlyPayment(rate, year, loan);
totalPayment = monthlyPay * 12 * year;
return totalPayment;
}
}
あなたがのコード例にあるように、彼ら(本の著者は)のテキストを追加できるようにする新しいスレッドを使用しますサーバーGUI。ただし、複数のクライアントを処理できるようにするには、whileループ内に新しいスレッドを作成して、個々のクライアントを処理します。
私は独立したJavaクラスとしてHandleAClientクラスを作成する代わりに、サーバ・クラスでそれを挿入しようとしたが、これはPlatform.runLaterコード
Platform.runLater(() -> {
textArea.appendText("The rate is : " + rate + "\n");
textArea.appendText("The number of years is: " + year + "\n");
textArea.appendText("Loan amount is: " + loan + "\n\n");});
だから私の質問に更新されていないサーバーのGUIになりました: HandleAClientクラスがServerクラスの内側にあり、HandleAClientクラスがServerを拡張する別のJavaクラスファイルにあるときには、なぜ動作しますか私はスレッドで何かをしなければならないと思いますか? HandleAClientクラスを独自のJavaクラスファイルに含めることができるように変更するにはどうすればよいですか?
私は興味があり、スレッドの仕組みをよく理解しようとしています。前もって感謝します。
更新 これは私にとっては役に立たないスタンドアロンクラスです。私はServerクラスを拡張し、TextAreaフィールドをServerクラスで保護しました。
class HandleAClient extends Server implements Runnable {
private Socket socket; // A connected socket
private double rate;
private int year;
private double loan;
public HandleAClient(Socket socket)
{
this.socket = socket;
}
/** run a thread */
public void run(){
try
{
// create data input and output streams
DataInputStream inputFromClient = new DataInputStream(socket.getInputStream());
DataOutputStream outputToClient = new DataOutputStream(socket.getOutputStream());
// continuously serve the client
while(true) {
// read data from client
rate = inputFromClient.readDouble();
year = inputFromClient.readInt();
loan = inputFromClient.readDouble();
// calculate monthly payment of loan and total payment
outputToClient.writeDouble(calculateMonthlyPayment(rate, year, loan));
outputToClient.writeDouble(calculateTotalPayment(rate, year, loan));
Platform.runLater(() -> {
textArea.appendText("The rate is : " + rate + "\n");
textArea.appendText("The number of years is: " + year + "\n");
textArea.appendText("Loan amount is: " + loan + "\n\n");});
}
}
catch(IOException e)
{
e.printStackTrace();
}
}
}
Platform.runLaterのコードは、クラスがServerクラスの内部にあるときのようにサーバーGUIに表示されません。なぜこれが本質的に起こるのか理解したい。
私は質問を理解しているか分かりません。 'HandleAClient'クラスは、アクセスする必要がある' Server'クラスのすべてのフィールドにアクセスできる限り、スタンドアロンクラスとして正常に動作するはずです(本当に内部クラスとトップレベルクラスの唯一の違いは内部クラスがその周囲のクラスのフィールドにアクセスできること)。あなたがトップレベルのクラスとしてそれを実装したとき、どのように 'textArea'へのアクセス権を与えましたか?動作しなかったスタンドアロン(最上位)の 'HandleAClient'クラスのフルバージョンを投稿できますか? –
はい元の投稿を更新して、うまくいかなかったクラスを追加しました。基本的には、ServerクラスでtextAreaフィールドをprotectedにし、ServerクラスをHandleAClientクラスに拡張しました。 – j2k1218
ここで更新するテキストエリアは、UIに表示するテキストエリアとは異なります。 UIを表示している 'Server'インスタンスに属するインスタンスを更新する必要があります。 –