无法在多线程中实现同步
Unable to achive synchronization in multithreading
我基本上是在尝试实现多人在线预订一辆出租车的真实示例。在我的代码中,我有 3 classes- 出租车、客户和服务器。
必须有多个客户(线程)和一辆出租车。但我无法做到这一点。每次我创建新客户时,都会创建一个新的出租车实例。
这是出租车class代码-
public class taxi {
boolean BOOKED=false;
String id;
void book(){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
BOOKED=true;
System.out.println("Customer "+Thread.currentThread().getName()+" BOOKED taxi");
}
void release(){
BOOKED=false;
System.out.println("Customer "+Thread.currentThread().getName()+" RELEASED taxi");
}
void setId(String id){
this.id=id;
}
String getId(){
return id;
}
}
客户class代码-
public class customer extends Thread {
taxi t=new taxi();
public void run(){
//System.out.println(t.hashCode());
t.setId(Thread.currentThread().getName());
System.out.println("Customer "+Thread.currentThread().getName()+" trying to BOOK taxi");
t.book();
System.out.println("Customer "+Thread.currentThread().getName()+" is currently USING taxi");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Customer "+Thread.currentThread().getName()+" RELEASING taxi");
t.release();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("taxi used by customer "+Thread.currentThread().getName()+" set id to "+t.getId());
}
}
服务器class代码-
public class server {
public static void main(String args[]){
customer A=new customer();
customer B=new customer();
customer C=new customer();
customer D=new customer();
Thread t=new Thread();
A.setName("A");
B.setName("B");
C.setName("C");
D.setName("D");
A.start();
B.start();
C.start();
D.start();
}
}
这是我的输出-
Customer B trying to BOOK taxi
Customer D trying to BOOK taxi
Customer A trying to BOOK taxi
Customer C trying to BOOK taxi
Customer B BOOKED taxi
Customer A BOOKED taxi
Customer A is currently USING taxi
Customer D BOOKED taxi
Customer D is currently USING taxi
Customer B is currently USING taxi
Customer C BOOKED taxi
Customer C is currently USING taxi
Customer C RELEASING taxi
Customer C RELEASED taxi
Customer D RELEASING taxi
Customer D RELEASED taxi
Customer A RELEASING taxi
Customer A RELEASED taxi
Customer B RELEASING taxi
Customer B RELEASED taxi
taxi used by customer D set id to D
taxi used by customer C set id to C
taxi used by customer A set id to A
taxi used by customer B set id to B
正如您所见,每辆出租车的 ID 是不同的,而不是相同的。
请帮忙。
我认为,Taxi class 不必是一个线程。通过将出租车 class 作为所有其他客户线程中的共享资源(具有同步方法的单例),我们可以在多线程中实现预期的同步。
关于您的代码的一些要点:
- 您应该只创建一个 Taxi 实例 class 并从 Customer class 中删除 taxi 实例变量并在服务器 class.
中实例化 Taxi
- 将您的客户class更改为乘坐共享出租车。可以在Customerclass中创建参数化构造函数来初始化共享出租车。
- setId 应该在方法 book 中调用,这样出租车的 Id 只能由想要预订出租车的线程更改。
你可以在Taxi class中使用wait/notify这种机制来实现同步:
public class Taxi {
Boolean BOOKED = false;
String id;
void book() throws InterruptedException {
synchronized (this) {
while (BOOKED) {
this.wait();
}
try {
setId(Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
BOOKED = true;
System.out.println("Customer " + Thread.currentThread().getName() + " BOOKED taxi");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
void release() throws InterruptedException {
synchronized (this) {
BOOKED = false;
System.out.println("Customer " + Thread.currentThread().getName() + " RELEASED taxi");
this.notifyAll();
}
}
void setId(String id) throws InterruptedException {
System.out.println("SETTING ID TO CUSTOMER " + Thread.currentThread().getName());
this.id = id;
}
String getId() {
return id;
}
}
客户:
public class Customer extends Thread {
Taxi taxi;
public Customer(Taxi taxi){
this.taxi = taxi;
}
public void run(){
//System.out.println(t.hashCode());
System.out.println("Customer "+Thread.currentThread().getName()+" trying to BOOK taxi");
try {
taxi.book();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Customer "+Thread.currentThread().getName()+" is currently USING taxi");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Customer "+Thread.currentThread().getName()+" RELEASING taxi");
try {
taxi.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
为什么每次都在客户中创建新的出租车?问题是:taxi t=new taxi();
。只需通过构造函数让出租车通过或使其成为全球性的或类似的东西。这样每个客户都会使用同一辆出租车。此外线程是危险的,所以你应该非常小心。你没有任何同步。我建议你不了解如何正确使用线程。我建议您阅读 synchronize
、volatile
、wait
、notify
、notifyAll
并尝试一些基本示例。我认为前两个在 Head First Java
中描述得很好。
Offtopic : 命名变量和方法时应遵循约定。
我基本上是在尝试实现多人在线预订一辆出租车的真实示例。在我的代码中,我有 3 classes- 出租车、客户和服务器。
必须有多个客户(线程)和一辆出租车。但我无法做到这一点。每次我创建新客户时,都会创建一个新的出租车实例。
这是出租车class代码-
public class taxi {
boolean BOOKED=false;
String id;
void book(){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
BOOKED=true;
System.out.println("Customer "+Thread.currentThread().getName()+" BOOKED taxi");
}
void release(){
BOOKED=false;
System.out.println("Customer "+Thread.currentThread().getName()+" RELEASED taxi");
}
void setId(String id){
this.id=id;
}
String getId(){
return id;
}
}
客户class代码-
public class customer extends Thread {
taxi t=new taxi();
public void run(){
//System.out.println(t.hashCode());
t.setId(Thread.currentThread().getName());
System.out.println("Customer "+Thread.currentThread().getName()+" trying to BOOK taxi");
t.book();
System.out.println("Customer "+Thread.currentThread().getName()+" is currently USING taxi");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Customer "+Thread.currentThread().getName()+" RELEASING taxi");
t.release();
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("taxi used by customer "+Thread.currentThread().getName()+" set id to "+t.getId());
}
}
服务器class代码-
public class server {
public static void main(String args[]){
customer A=new customer();
customer B=new customer();
customer C=new customer();
customer D=new customer();
Thread t=new Thread();
A.setName("A");
B.setName("B");
C.setName("C");
D.setName("D");
A.start();
B.start();
C.start();
D.start();
}
}
这是我的输出-
Customer B trying to BOOK taxi
Customer D trying to BOOK taxi
Customer A trying to BOOK taxi
Customer C trying to BOOK taxi
Customer B BOOKED taxi
Customer A BOOKED taxi
Customer A is currently USING taxi
Customer D BOOKED taxi
Customer D is currently USING taxi
Customer B is currently USING taxi
Customer C BOOKED taxi
Customer C is currently USING taxi
Customer C RELEASING taxi
Customer C RELEASED taxi
Customer D RELEASING taxi
Customer D RELEASED taxi
Customer A RELEASING taxi
Customer A RELEASED taxi
Customer B RELEASING taxi
Customer B RELEASED taxi
taxi used by customer D set id to D
taxi used by customer C set id to C
taxi used by customer A set id to A
taxi used by customer B set id to B
正如您所见,每辆出租车的 ID 是不同的,而不是相同的。
请帮忙。
我认为,Taxi class 不必是一个线程。通过将出租车 class 作为所有其他客户线程中的共享资源(具有同步方法的单例),我们可以在多线程中实现预期的同步。
关于您的代码的一些要点:
- 您应该只创建一个 Taxi 实例 class 并从 Customer class 中删除 taxi 实例变量并在服务器 class. 中实例化 Taxi
- 将您的客户class更改为乘坐共享出租车。可以在Customerclass中创建参数化构造函数来初始化共享出租车。
- setId 应该在方法 book 中调用,这样出租车的 Id 只能由想要预订出租车的线程更改。
你可以在Taxi class中使用wait/notify这种机制来实现同步:
public class Taxi {
Boolean BOOKED = false;
String id;
void book() throws InterruptedException {
synchronized (this) {
while (BOOKED) {
this.wait();
}
try {
setId(Thread.currentThread().getName());
} catch (InterruptedException e) {
e.printStackTrace();
}
BOOKED = true;
System.out.println("Customer " + Thread.currentThread().getName() + " BOOKED taxi");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
void release() throws InterruptedException {
synchronized (this) {
BOOKED = false;
System.out.println("Customer " + Thread.currentThread().getName() + " RELEASED taxi");
this.notifyAll();
}
}
void setId(String id) throws InterruptedException {
System.out.println("SETTING ID TO CUSTOMER " + Thread.currentThread().getName());
this.id = id;
}
String getId() {
return id;
}
}
客户:
public class Customer extends Thread {
Taxi taxi;
public Customer(Taxi taxi){
this.taxi = taxi;
}
public void run(){
//System.out.println(t.hashCode());
System.out.println("Customer "+Thread.currentThread().getName()+" trying to BOOK taxi");
try {
taxi.book();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Customer "+Thread.currentThread().getName()+" is currently USING taxi");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("Customer "+Thread.currentThread().getName()+" RELEASING taxi");
try {
taxi.release();
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
为什么每次都在客户中创建新的出租车?问题是:taxi t=new taxi();
。只需通过构造函数让出租车通过或使其成为全球性的或类似的东西。这样每个客户都会使用同一辆出租车。此外线程是危险的,所以你应该非常小心。你没有任何同步。我建议你不了解如何正确使用线程。我建议您阅读 synchronize
、volatile
、wait
、notify
、notifyAll
并尝试一些基本示例。我认为前两个在 Head First Java
中描述得很好。
Offtopic : 命名变量和方法时应遵循约定。