我是Java的新手,并试图了解同步的工作原理。所以我创建了一个平面预订系统,我可以模拟多个用户尝试进行预订并使用同步来获得正确的输出。
既然它有效,我在想它是如何在现实世界中起作用的。例如,假设应用程序是基于Swing构建的,这是一个多用户应用程序。为简单起见,我们假设只有两个平面'AAA'和'BBB'。该应用程序可以安装在每个售票柜台代理的计算机,机场的售货亭以及不同旅行社的计算机中,并且所有这些都可以访问同一个数据库。
在这种情况下,每个用户/计算机都有自己的Reserve类,Transaction类和Plane类的实例。因此,Transaction类中只有一个线程/请求,并且没有同步。
我的问题是,实际上如何设计/实现像此预订系统这样的mutli用户应用程序,以便所有用户都访问Transacion类的一个实例,以便可以进行同步。你也可以看看这个问题,我怎样才能构建不同玩家在不同计算机上玩的多用户游戏。还有一个例子是银行系统,当应用程序在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;
}
}
答案 0 :(得分:2)
要么
a)您依赖数据库存储过程(确保原子性)来执行操作。
b)您只有一个实例(服务器)来保存关键部分。客户端向它发出请求,服务器告诉是否有座位可用(操作成功)或者没有(操作失败)。
现实世界的操作主要是b,可以使用a。
答案 1 :(得分:2)
从表面上看,你可以制作所有Transaction
方法synchronized
:这会让你互相排斥。
然而,实际上,没有系统是这样设计的。服务器端应用程序未建模为单个同步对象。相反,持久状态在支持ACID事务(原子,并发,隔离和持久)的关系数据库中维护,而Transaction
对象的等价物是在Java级别不需要同步的无状态单例对象。这样的对象将被称为服务bean 。它通常在依赖注入容器(如Spring)中创建,并且它将连接到一堆其他对象,例如DAO(数据访问对象),这些对象将依次实现与a的交互的低级逻辑。数据库。依赖注入容器可以轻松地以声明方式构建互连对象的复杂图形。典型的企业应用程序,例如航空公司的预订系统,至少包含数十个服务bean和更多DAO,它们连接到各种后端系统。