1

私はJavaを初めて使用し、同期がどのように機能するかを理解しようとしていました。そこで、飛行機予約システムを作成し、予約を試みている複数のユーザーをシミュレートし、同期を使用して正しい出力を取得することができます。

それが機能するようになったので、私はこれが現実の世界でどのように機能するかを考えています。たとえば、アプリケーションがSwing上に構築されており、これがマルチユーザーアプリケーションであるとします。簡単にするために、平面「AAA」と「BBB」が2つしかないものと仮定します。このアプリケーションは、チケットカウンターエージェントの各コンピューター、空港のキオスク、およびさまざまな旅行代理店のコンピューターにインストールでき、それらすべてが同じデータベースにアクセスします。

この場合、各ユーザー/コンピューターには、Reserveクラス、Transactionクラス、およびPlaneクラスの独自のインスタンスがあります。したがって、Transactionクラスにはスレッド/リクエストが1つだけあり、同期はありません。

私の質問は、この予約システムのようなマルチユーザーアプリケーションが実際にどのように設計/実装され、すべてのユーザーがTransacionクラスの1つのインスタンスにアクセスして同期が行われるようにするかということです。この質問は、さまざまなコンピューターでさまざまなプレーヤーがプレイするマルチユーザーゲームを作成するにはどうすればよいかということも考えられます。もう1つの例は、アプリケーションがATMとTellerのマシンで実行されているときに、預金、引き出し、および送金を行う銀行システムです。

///////////////////////////////

Reserve.java--->ユーザーが行った各リクエストのエントリポイント

/////////////////////////////

import java.io.IOException;

public class Reserve {

static int queryseatsavailableinx;
static int queryseatsavailableiny;

static
{
    seats s = null;
    try {
        s = new seats();
    } catch (IOException e1) {
        // TODO Auto-generated catch block
        e1.printStackTrace();
    }
    try {
        queryseatsavailableinx = s.getseatsinplanex("AAA");
        queryseatsavailableiny = s.getseatsinplanex("BBB");
    } catch (IOException e) {
        e.printStackTrace();
    }
}

static final Plane x1 = new Plane("AAA", 001, queryseatsavailableinx );
static final Plane y1 = new Plane("BBB", 002, queryseatsavailableiny);
static final Transaction trans = new Transaction();

public static void main(String[] args) throws InterruptedException {

    Thread t1 = new Thread(new Runnable() {

        public void run() {
            trans.getPlaneInfo(x1);
        }
    });

    Thread t2 = new Thread(new Runnable() {

        public void run() {
            //trans.getPlaneInfo(x1);
            trans.reserveSeats(x1,3);
        }
    });

    Thread t3 = new Thread(new Runnable() {

        public void run() {
            //trans.getPlaneInfo(y1);
            trans.reserveSeats(y1,8);
        }
    });

    Thread t4 = new Thread(new Runnable() {

        public void run() {
            //trans.getPlaneInfo(x1);
            trans.reserveSeats(x1,2);
        }
    });

    t1.start();
    t2.start();
    t3.start();
    t4.start();

    t1.join();
    t2.join();
    t3.join();
    t4.join();
 }

}

///////////////////////////////

Transaction.java--->実際のトランザクションはここで発生します

/////////////////////////////

public class Transaction {

public void getPlaneInfo(Plane x){
    synchronized(this){
        int number =  x.getSeatCapacity();
        String planename=x.getPlaneName();
        System.out.printf("The number of seats in plane %s is %d\n",planename,number);
    }

}

public void reserveSeats(Plane x, int seatstobereserved) {
    synchronized(this){
    x.updateSeatCapacity(seatstobereserved);
    }
  }
 }

///////////////////////////////

Plane.java--->飛行機に関する情報

/////////////////////////////

final public class Plane {

private String planename = null;
private int planeid = 0;
private int availableseatcapacity = 0;

Plane(String planename, int planeid, int seatcapacity) {
    this.planename = planename;
    this.planeid = planeid;
    this.availableseatcapacity = seatcapacity;
}

public String getPlaneName() {
    return planename;
}

public int getPlaneId() {
    return planeid;
}

public int getSeatCapacity() {
    return availableseatcapacity;
}

public void updateSeatCapacity(int reservedseats) {
    availableseatcapacity -= reservedseats;
    System.out.printf("\n%d Seats successfully reserved and remaining seats " +
            "in the plane %s are %d\n",reservedseats, planename,availableseatcapacity);

 }

}

///////////////////////////////

Seats.java --->ユーザーがリクエストを行うたびにシミュレートするために、「利用可能なシートの数」が共通のデータソース/dbから取得されます。/////////////////////////////

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.EOFException;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

final public class seats {

seats() throws IOException {
    DataOutputStream di1 = new DataOutputStream(new FileOutputStream(
            "\\PlaneReservation\\bin\\a.bin"));
    DataOutputStream di2 = new DataOutputStream(new FileOutputStream(
            "\\PlaneReservation\\bin\\b.bin"));

    di1.writeInt(300);
    di2.writeInt(200);
    di1.flush();
    di2.flush();
    di1.close();
    di2.close();
}

public int getseatsinplanex(String s) throws IOException {
    if (s.equals("AAA")) {
        FileInputStream fis1 = new FileInputStream("\\PlaneReservation\\bin\\a.bin");
        DataInputStream dis1 = new DataInputStream(fis1);
        int number = 0;
        boolean eof = false;
        while (!eof) {
            try {
                number = dis1.readInt();
            //  System.out.println(number);
            } catch (EOFException eofx) {
                eof = true;
                dis1.close();
            }
        }
        return number;
    } else if (s.equals("BBB")) {
        FileInputStream fis2 = new FileInputStream("\\PlaneReservation\\bin\\b.bin");
        DataInputStream dis2 = new DataInputStream(fis2);
        int number = 0;
        boolean eof = false;
        while (!eof) {
            try {
                number = dis2.readInt();
                //System.out.println(number);
            } catch (EOFException eofx) {
                eof = true;
                dis2.close();
            }
        }
        return number;
    }
    return 0;
 }
}
4

2 に答える 2

2

また

a)操作を実行するために(原子性を保証する)データベースストアドプロシージャに依存します。

b)クリティカルセクションを保持するインスタンス(サーバー)は1つだけです。クライアントはそれに要求を実行し、サーバーは利用可能なシートがあるか(操作が成功した)、またはなかったか(操作が失敗した)を通知します。

実世界の工作員は主にbであり、aを使用できます。

于 2012-12-02T19:01:46.473 に答える
2

症状として、すべてTransactionのメソッドを作成しますsynchronized。これにより、相互排除が可能になります。

しかし実際には、そのように設計されたシステムはありません。サーバー側のアプリケーションは、単一の同期オブジェクトとしてモデル化されていません。むしろ、耐久性のある状態は、ACIDトランザクション(アトミック、同時、分離、および耐久性)をサポートするリレーショナルデータベースで維持され、オブジェクトに相当するTransactionものは、Javaレベルでの同期を必要としないステートレスシングルトンオブジェクトです。このようなオブジェクトはサービスBeanと呼ばれます。これは通常、Springなどの依存性注入コンテナ内で作成され、DAO(データアクセスオブジェクト)などの他のオブジェクトの束に接続されます。DAOは、データベース。依存性注入コンテナを使用すると、相互接続されたオブジェクトの複雑なグラフを宣言的に作成することが簡単になります。航空会社の予約システムなどの一般的なエンタープライズアプリケーションには、少なくとも数十のサービスBeanと、さまざまなバックエンドシステムに接続するさらに多くのDAOが含まれています。

于 2012-12-02T19:05:39.713 に答える