私の仕事は、持っているプログラムを作成することです:
- クラス
Client
- クラス
Gate
- クラス
Museum
Client
入り、去るMuseum
使用してGate
クラスを。博物館は一度に5つのクライアントの最大を持つことができます。
I入力のletのは、1000年を言うときClients
、いくつかの時点で、出力は私に不要な数字を与えます。
出力例:
Client (358) is leaving the Museum! number of customers: 2
Client (214) is entering the Museum! number of customers: 3
Client (214) is leaving the Museum! number of customers: 2
Client (73) is entering the Museum! number of customers: 5
Client (73) is leaving the Museum! number of customers: 5
Client (397) is entering the Museum! number of customers: 5
Client (76) is entering the Museum! number of customers: 6
----------------------------------------------------------------
Client (930) is entering the Museum! number of customers: 7
Client (930) is leaving the Museum! number of customers: 6
Client (308) is entering the Museum! number of customers: 6
Client (183) is entering the Museum! number of customers: 6
Client (183) is leaving the Museum! number of customers: 5
----------------------------------------------------------------
Client (647) is entering the Museum! number of customers: 7
Client (647) is leaving the Museum! number of customers: 6
----------------------------------------------------------------
Client (540) is entering the Museum! number of customers: 7
私は、クライアントがいくつかのランダムな時間に入力しようとしていることを期待していて、博物館で5つの以上のクライアントがある場合、彼らは他のスレッドがそれのタスクを終了するのを待つ必要があります。
ここに私のコードは次のとおりです。
Client.java
package client;
import gate.Gate;
import museum.Museum;
import java.util.Random;
public class Client extends Thread {
private static int id = 0;
private int clientID;
public Client() {
Client.id++;
this.clientID = id;
}
@Override
public void run() {
this.enterMuseum();
this.leaveMuseum();
}
///////////////////////////////////////////////////////////////////////////////////
private void enterMuseum() {
try {
Thread.sleep(new Random().nextInt(401) + 100);
} catch (InterruptedException e) {
e.printStackTrace();
}
while (true) {
if (Gate.atomCustomer.get() < 5) {
Museum.getGate(0).enter(this);
break;
}
}
}
private void leaveMuseum() {
Museum.getGate(1).exit(this);
}
public int getClientId() {
return this.clientID;
}
////////////////////////////////////////////////////////////////////////////////////
}
Gate.java
package gate;
import client.Client;
import java.util.concurrent.atomic.AtomicInteger;
public class Gate {
public static AtomicInteger atomCustomer = new AtomicInteger();
public Gate() {
}
public void enter(Client client) {
if (atomCustomer.get() > 5) {
System.out.println("----------------------------------------------------------------");
}
atomCustomer.incrementAndGet();
System.out.println("Client (" + client.getClientId() + ") is entering the Museum!" +
" number of customers: " + atomCustomer.get());
}
public void exit(Client client) {
atomCustomer.decrementAndGet();
System.out.println("Client (" + client.getClientId() + ") is leaving the Museum!" +
" number of customers: " + atomCustomer.get());
}
}
Museum.java
package museum;
import gate.Gate;
public class Museum {
private static Gate[] gate = new Gate[2];
public Museum() {
gate[0] = new Gate();
gate[1] = new Gate();
}
public static Gate getGate(final int numberOfGate) {
return Museum.gate[numberOfGate];
}
}
ApplicationTest.java
import client.Client;
import museum.Museum;
import java.util.ArrayList;
import java.util.Scanner;
public class ApplicationTest implements Runnable {
private static int NUMBER_OF_CLIENTS = 0;
private static ArrayList<Client> listOfClients;
private static Scanner sc = new Scanner(System.in);
public static void main(String[] args) {
new Thread(new ApplicationTest()).start();
}
private static void init() {
while (NUMBER_OF_CLIENTS < 5) {
System.out.println("How many clients?( > 5): ");
NUMBER_OF_CLIENTS = sc.nextInt();
}
listOfClients = new ArrayList<>(NUMBER_OF_CLIENTS);
new Museum();
for (int i = 0; i < NUMBER_OF_CLIENTS; i++) {
ApplicationTest.listOfClients.add(new Client());
}
for (Client c : listOfClients) {
c.start();
}
}
@Override
public void run() {
ApplicationTest.init();
}
}
私は任意の助けのために感謝するでしょう。御時間ありがとうございます。Q.
いくつかの提案は、公共の静的変数とmuseum.getGateなどの静的メソッド()または原子顧客のカウンタを使用していない(それが何を使用しています誰が理解することが難しくなります)。また、Clientクラスは、完全に「カウンタ」のロジックから分離する必要があります。つまり、クライアントは単にgate.enterを呼び出す必要があります()、およびアクセスチェックは、門や博物館のいずれかで行うべきです。
そして、あなたがクライアントに「許可」を割り当てようと「クリティカル」の部分は、であり、
while (true) {
if (Gate.atomCustomer.get() < 5) {
//use museum.tryEnter() instead..
Museum.getGate(0).enter(this);
break;
}
}
ここでは、2つのスレッドが(取得呼び出す場合)、同時に、彼らは顧客の数が例えばあることがわかります両方。4、彼らは両方(並行処理の問題)を入力します。
必ず1つのクライアントのみが許可証を取得させるための一つの方法は、のようないくつかの同期方法にネストされた呼び出しを追加することです
private synchronized boolean tryEnter() {
if (counter<5) {
counter++;
return true;
}
else {
return false;
}
}
しかし、割り当て許可に良い方法は(あなたも忙しいループすることを必要としないように)セマフォを使用することです。https://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Semaphore.html