假设又三个车位(可以用boolean[]数组来表示车库)可以停车,写一个程序模拟多个用户开车离开,停车入库的效果。注意车位有车的时候不能停车。
开始时,车位为空,只准进行倒车入库操作(一共有三个车位,所以最多同时有三辆车进行倒库),超过三辆车以后,不允许车进入;同时,当某个车位有车的时候,新的车辆不能进入该车位;汽车出库完成,允许新的车进入其中。
用户(User)提供车位信息,倒车入库方法和出库离开方法,检查剩余车位并且返回空余车位的位置
/**
# 题目
假设又三个车位(可以用boolean[]数组来表示车库)可以停车,
写一个程序模拟多个用户开车离开,停车入库的效果。注意车位有车的时候不能停车。
*/
/**
* 用户类,封装车位信息,提供入库和出库方法
*/
class User{
private boolean[] parking ={false,false,false};
public synchronized int findSpareParking(){
for(int i=0;i<parking.length; i++){
if(!parking[i]){
return i;
}
}
return -1;
}
/**
* 倒车入库,出库离开
*/
public synchronized void move(){
int p;
if((p=findSpareParking())>=0){
//停车进入
parking[p]=true;
System.out.println(Thread.currentThread().getName()+"在车位"+p+"倒车入库");
//模拟实际汽车在车位停留一定思维时间
//唤醒其他线程
notifyAll();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//出库
parking[p] = false;
System.out.println(Thread.currentThread().getName() +"在车位"+p+ "出库离开");
}
}
}
class CarThread extends Thread {
private String name;
private User user;
public CarThread(String name, User user) {
super(name);
this.user = user;
}
@Override
public void run() {
user.move();
}
}
public class Problem2 {
public static void main(String[] args) {
User user = new User();
//创建多个线程和用户
for (int i=0;i<12;i++){
new CarThread("car"+i,user).start();
}
}
}
car0在车位0倒车入库
car0在车位0出库离开
car11在车位0倒车入库
car11在车位0出库离开
car10在车位0倒车入库
只有一个车位被启用,分析原因是因为move方法里面虽然有休眠和notifyAll()方法,但是程序实际上还是顺序执行
每位用户创建两个线程:倒车入库线程和出库离开线程;但是这个时候出现了新的问题,怎样知道某辆汽车停在哪个车位上呢?只有认识到这一点,才能完成汽车出库的操作。因此需要额外定义一个数组cars,同来表示汽车入库以后的车位信息。汽车在p位置入库,parking[p]=true,cars[p]=“car_name”;出库的时候,首先需要确保当前线程所代表的汽车的确是进入到车位当中,假设其位置是p,出库操作为parking[p]=false,cars[p]=“null”
/**
* # 题目
* 假设又三个车位(可以用boolean[]数组来表示车库)可以停车,
* 写一个程序模拟多个用户开车离开,停车入库的效果。注意车位有车的时候不能停车。
*/
/**
* 用户类,封装车位信息,提供入库和出库方法
*/
class User {
private boolean[] parking = {false, false, false};
private String[] cars = new String[3];
public synchronized int findSpareParking() {
for (int i = 0; i < parking.length; i++) {
if (!parking[i]) {
return i;
}
}
return -1;
}
public synchronized int findParkingWithCar() {
for (int i = 0; i < parking.length; i++) {
if (parking[i] && cars[i] != null && cars[i].equals(Thread.currentThread().getName())) {
return i;
}
}
return -1;
}
/**
* 倒车入库
*/
public synchronized void move() {
int p;
String name = Thread.currentThread().getName();
if((p= findSpareParking())>=0){
//停车进入
parking[p] = true;
cars[p] = name;
System.out.println(name + "在车位" + p + "倒车入库");
//模拟实际汽车在车位停留一定思维时间
//唤醒其他线程
notifyAll();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
/**
* 出库离开
*/
public synchronized void leave() {
//出库离开
if((p = findParkingWithCar())>=0){
parking[p] = false;
cars[p] = null;
System.out.println(Thread.currentThread().getName() + "在车位" + p + "出库离开");
notifyAll();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class MoveThread extends Thread {
private String name;
private User user;
public MoveThread(String name, User user) {
super(name);
this.user = user;
}
@Override
public void run() {
user.move();
}
}
class LeaveThread extends Thread {
private String name;
private User user;
public LeaveThread(String name, User user) {
super(name);
this.user = user;
}
@Override
public void run() {
user.leave();
}
}
public class Problem2 {
public static void main(String[] args) {
User user = new User();
//创建多个线程和用户
for (int i = 0; i < 12; i++) {
new MoveThread("car" + i, user).start();
new LeaveThread("car" + i, user).start();
}
}
}
但是实际运行的结果发现每次只有少量的几次记录,如下所示
car0在车位0倒车入库
car11在车位1倒车入库
car10在车位2倒车入库
car0在车位0出库离开
明明在main方法里面创建了24个线程,属于12辆汽车(包括入库和出库),为什么最终每次只有4个线程运行?
因为在main方法里面的确创建了24个线程,但是其中很多线程在执行run方法时,当不能满足里面的if判断的时候,线程将直接正常结束,这是我们不希望看见的,我们应该让其阻塞,直到满足if判断条件,因此在每个同步方法前面应该加入while判断,如果不满足,阻塞线程。
/**
* # 题目
* 假设又三个车位(可以用boolean[]数组来表示车库)可以停车,
* 写一个程序模拟多个用户开车离开,停车入库的效果。注意车位有车的时候不能停车。
*/
/**
* 用户类,封装车位信息,提供入库和出库方法
*/
class User {
private boolean[] parking = {false, false, false};//车位信息
private String[] cars = new String[3];//表示每个车位所停的汽车的名称,没有停车时为null
/**
* 从左往右找到空闲的车位
* @return
*/
public synchronized int findSpareParking() {
for (int i = 0; i < parking.length; i++) {
if (!parking[i]) {
return i;
}
}
return -1;
}
/**
* 出库操作判断,找到能够出库的汽车
* @return
*/
public synchronized int findParkingWithCar() {
for (int i = 0; i < parking.length; i++) {
//确保当前线程所代表的汽车的确是进入到车位当中
if (parking[i] && cars[i] != null && cars[i].equals(Thread.currentThread().getName())) {
return i;
}
}
return -1;
}
/**
* 倒车入库
*/
public synchronized void move() {
int p;
String name = Thread.currentThread().getName();
//不满足倒车入库条件阻塞当前线程
while (findSpareParking() < 0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
p= findSpareParking();
//停车进入
parking[p] = true;
cars[p] = name;
System.out.println(name + "在车位" + p + "倒车入库");
//模拟实际汽车在车位停留一定思维时间
//唤醒其他线程
notifyAll();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
/**
* 出库离开
*/
public synchronized void leave() {
int p;
//不满足出库离开条件,阻塞线程
while (findParkingWithCar() < 0) {
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//出库离开
p = findParkingWithCar();
parking[p] = false;
cars[p] = null;
System.out.println(Thread.currentThread().getName() + "在车位" + p + "出库离开");
notifyAll();
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class MoveThread extends Thread {
private String name;
private User user;
public MoveThread(String name, User user) {
super(name);
this.user = user;
}
@Override
public void run() {
user.move();
}
}
class LeaveThread extends Thread {
private String name;
private User user;
public LeaveThread(String name, User user) {
super(name);
this.user = user;
}
@Override
public void run() {
user.leave();
}
}
public class Problem2 {
public static void main(String[] args) {
User user = new User();
//创建多个线程和用户
for (int i = 0; i < 12; i++) {
new MoveThread("car" + i, user).start();
new LeaveThread("car" + i, user).start();
}
}
}