解决方案 »

  1.   

    这个问题并不复杂啊,使用wait,notify就可以了啊。然后加上synchronized同步就行了。
      

  2.   

    所以其实你感觉到比较难模拟的几点:
    1. 线程如何通信,这个可以用静态变量的方式,比如一个汽车发现有问题,设置一个静态变量值,其他的线程定时的去检查有没有其他的汽车发现问题,如果有的话,就暂停。2. 线程如何暂停,这个只能定时检查,比如一个逻辑循环检查一次,或者每个逻辑操作检查一次3. 如何模拟修复,这个简单,sleep一下就行了
      

  3.   

    就是用好notify唤醒,和线程的暂停
      

  4.   

    已上代码,根据大家的提供思路重新模拟了一下,目前有个情况是,一旦某一辆汽车发现道路故障,导致所有线程暂停,请各位指正!
    public class Car implements Runnable{ public void run() {
    for (int i=0;i<1000;i++) {
    //这里假设每一个i是一个道路长度单位
    System.out.println(Thread.currentThread().getName() +"汽车前进:"+i);
    //模拟道路损坏障碍
    int rand = getRondomNumBetweenAB(1,500) ;
    if (rand == 300) {
    System.out.println("发现故障,开始处理");
    synchronized (this) {
    try {
    this.wait();
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }
    try {
    Thread.sleep(5000);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    System.out.println("故障处理完成");
    this.notify();
    }
    }

    }

    public int getRondomNumBetweenAB(int a, int b) {
    return (int) Math.round(Math.random()*(b-a)+a);
    }
    }
    public class Way {

    public static void main(String args[]) {
    Car car = new Car();
    Thread thread1 = new Thread(car);
    Thread thread2 = new Thread(car);
    Thread thread3 = new Thread(car);
    thread1.start();
    thread2.start();
    thread3.start();
    }}
      

  5.   


    你在线程中用this.wait的话,把当前线程阻塞了,所以是每个线程遇到rand == 300的时候,自己把自己阻塞了,而且没法再收到notify了这种情况,肯定要用同一个对象来wait和notify
      

  6.   

    将上面的改写了一下,
    //构建道路类
    public class Way5 {
    public static void main(String args[]) {

    Breaker b = new Breaker();
    Car5 car = new Car5(b);
    Thread thread1 = new Thread(car);
    Thread thread2 = new Thread(car);
    Thread thread3 = new Thread(car);
    thread1.start();
    thread2.start();
    thread3.start();
    System.out.println("HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH");
    }
    }
    //汽车线程类
    public class Car5 implements Runnable {
    Breaker b; public Car5(Breaker b) {
    this.b = b;
    } public void run() {
    for (int i = 0; i < 30; i++) {
    // 这里假设每一个i是一个道路长度单位
    System.out.println(Thread.currentThread().getName() + "汽车前进:" + i);
    // 模拟道路损坏障碍
    int rand = getRondomNumBetweenAB(1, 10);
    if (rand == 9) {
    System.out.println(Thread.currentThread().getName() + "发现故障,开始处理========================");
    b.repair();
    System.out.println(Thread.currentThread().getName() + "故障处理完成=============================");
    }
    } } public int getRondomNumBetweenAB(int a, int b) {
    return (int) Math.round(Math.random() * (b - a) + a);
    }
    }//将道路损坏也视作一个类Breaker ,并且带有修复功能
    public class Breaker {

    private boolean needRepair = false;

    public synchronized void repair() {
    System.out.println("进入repar方法");
    System.out.println(Thread.currentThread().getName() +"需要修复哦=====================================");
    synchronized (this) {
    try {
    Thread.sleep(2000);
    this.wait();

    System.out.println(Thread.currentThread().getName()+"修复中=====================================");
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();

    System.out.println(Thread.currentThread().getName()+"修复完成了哦=====================================");
    needRepair = false;

    this.notifyAll();
    }

    }

    public synchronized void doRepair() {
    this.needRepair = true;
    }}以上程序还是会出现2个问题:
    1、一个线程在调用Breaker(道路损坏)方法repair(修复功能)的时候,其他线程依然会执行,而实际上需要其他汽车线程立即暂停
    2、线程不能退出
    请高手指正!
      

  7.   


    你在线程中用this.wait的话,把当前线程阻塞了,所以是每个线程遇到rand == 300的时候,自己把自己阻塞了,而且没法再收到notify了这种情况,肯定要用同一个对象来wait和notify

    按照你的提示在9楼写了一个代码,不过还是有些小问题,辛苦看一看哪
      

  8.   


    因为你在repair中只是把当前线程wait了,当时其他线程并没有进入wait状态。
    这种情况,需要加入一个状态开关,如果某个线程在修复了,则其他线程需要根据状态位判断来进入wait。
    建议你先好好看一下wait和notify的定义再写代码,机制理解清楚了
    推荐你看看http://lavasoft.blog.51cto.com/62575/99155
      

  9.   

    import java.util.Random;public class ThreadTest {
    private boolean repairing; public static void main(String[] args) {
    ThreadTest threadTest = new ThreadTest();
    new Thread(threadTest.new MyCarThread(), "a").start();
    new Thread(threadTest.new MyCarThread(), "b").start();
    new Thread(threadTest.new MyCarThread(), "c").start();
    } class MyCarThread implements Runnable { @Override
    public void run() {
    while (true) {

    while (repairing) {
    System.out.println(Thread.currentThread().getName()+ "车辆正在等待道路修复。。");
    try {
    Thread.sleep(5000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }

    System.out.println(Thread.currentThread().getName() + "车辆运行中。。");

    //发现路坏了
    int i = new Random().nextInt(10);
    if (i == 5) {
    repairing = true;
    System.out.println(Thread.currentThread().getName()+ "发现道路坏了,通知所有其它车辆先暂停行驶,正在修复,预计要5秒");
    try {
    Thread.sleep(5000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(Thread.currentThread().getName()+ "发现把道路修复了,各车辆可以继续行驶。");
    repairing = false;
    } try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    } }
    }
      

  10.   

    多谢wu244534279的回答,有那么些感觉了,发现把程序中的sleep时间设短,就会发现有可能导致某一辆车没有及时停车,请问这个怎么解决呢
      

  11.   

    这个我也不知道咋搞的了,只能说像现实那样,你的车开太快了(sleep时间短),那么你想停车也不可能马上停,但是的确踩了刹车,所以总是会停的。
    暂时没找你这个问题的解决办法,想到了再告诉你。
      

  12.   

    多谢wu244534279的回答,有那么些感觉了,发现把程序中的sleep时间设短,就会发现有可能导致某一辆车没有及时停车,请问这个怎么解决呢关键变量最好加同步哦。
      

  13.   

    Car.java
    public class Car implements Runnable { private int repairfactor;
    private String carName;
    final Lock lock;
    final Condition condition; public Car(int repairfactor, String carName, Lock lock, Condition condition) {
    this.carName = carName;
    this.repairfactor = repairfactor;
    this.lock = lock;
    this.condition = condition;
    } void process(RoadFault road) {
    try {
    lock.lock();
    int sleep = 10000 * road.getFault() / repairfactor;
    System.out.println("Sleep time : " + sleep);
    Thread.sleep(sleep);
    condition.signalAll();
    RoadFaultManager.getRoadFaultManager().setFault(false); } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    } finally {
    lock.unlock();
    }
    } public void run() {
    // TODO Auto-generated method stub for (int i = 0; i < 1000; i++) { // 这里假设每一个i是一个道路长度单位
    System.out.println(this.toString() + " car moving " + i);
    // 模拟道路损坏障碍
    int rand = getRondomNumBetweenAB(1, 500);
    if (rand == 300) {
    System.out.println(this.toString()
    + " : find fault , begin process "); try {
    lock.lock(); final RoadFault road = RoadFaultManager
    .getRoadFaultManager().getRoad(); if (road == null) {
    continue;
    }
    RoadFaultManager.getRoadFaultManager().setFault(true);
    new Thread(new Runnable() {
    public void run() {
    // TODO Auto-generated method stub
    process(road);
    }
    }).start();//start another thread to process repair road
    condition.await();
    } catch (Exception e) { } finally {
    lock.unlock();
    } System.out.println(this.toString()
    + " : finish processing fault");
    } else if (RoadFaultManager.getRoadFaultManager().isFault()) {
    try {
    lock.lock(); condition.await();
    } catch (Exception e) { } finally { lock.unlock();
    }
    }
    }
    } public String toString() {
    return "carName " + carName + " repairfactor " + repairfactor;
    } public int getRondomNumBetweenAB(int a, int b) {
    return (int) Math.round(Math.random() * (b - a) + a);
    }}RoadFaultManager.java 
    public class RoadFaultManager { private static RoadFaultManager roadFaultManagerInstance = new RoadFaultManager(); private boolean fault;

    public static RoadFaultManager getRoadFaultManager() { if (roadFaultManagerInstance == null) {
    synchronized (RoadFaultManager.class) {
    roadFaultManagerInstance = new RoadFaultManager();
    }
    }
    return roadFaultManagerInstance;
    } RoadFaultManager() {
    init(5);
    fault = false;
    }

    public RoadFault getRoad(){

    return queue.poll();

    }


    /**
     * @return the fault
     */
    public boolean isFault() {
    return fault;
    } /**
     * @param fault the fault to set
     */
    public void setFault(boolean fault) {
    this.fault = fault;
    } private void init(int num) { queue = new LinkedBlockingQueue<RoadFault>(); for (int i = 0; i < num; i++) { int a = getRondomNumBetweenAB(i, i + 10); queue.add(new RoadFault(a, "fault" + i));
    } } private Queue<RoadFault> queue = null; public static int getRondomNumBetweenAB(int a, int b) {
    return (int) Math.round(Math.random() * (b - a) + a);
    }
    }class RoadFault { private int fault; private String name; RoadFault(int fault, String name) {
    this.fault = fault;
    this.name = name;
    } /**
     * @return the fault
     */
    public int getFault() {
    return fault;
    } /**
     * @return the name
     */
    public String getName() {
    return name;
    }}
    Way.java
    public class Way {
    public static void main(String args[]) {

    Lock lock = new ReentrantLock();
    Condition conditon  = lock.newCondition();
    Car car1 = new Car(10,"Car1" , lock, conditon);
    Car car2 = new Car(20,"Car2" , lock, conditon);
    Car car3 = new Car(25,"Car3" , lock, conditon);
    Thread thread1 = new Thread(car1);
    Thread thread2 = new Thread(car2);
    Thread thread3 = new Thread(car3);
    thread1.start();
    thread2.start();
    thread3.start();
    }

    }
      

  14.   

    Quote: 引用 16 楼 lysnow_oss 的回复:

    Quote: 引用 14 楼 wumachangxi7 的回复:

    Quote: 引用 13 楼 wu244534279 的回复:
    怎么加,将while方法中的代码加上 synchronized (this) {}代码块问题依旧存在
      

  15.   

    如果加锁的话,就很不科学了,虽然能解决上面所说的刹车问题,总感觉是这条路上每次只能行驶一辆车。。
    import java.util.Random;public class ThreadTest { byte[] lock = new byte[0]; public static void main(String[] args) {
    ThreadTest test = new ThreadTest();
    new Thread(test.new CarThread(), "a").start();
    new Thread(test.new CarThread(), "b").start();
    new Thread(test.new CarThread(), "c").start();
    } class CarThread implements Runnable { @Override
    public void run() {
    while (true) {
    synchronized (lock) {
    String carName = Thread.currentThread().getName();
    System.out.println(carName + "车正在行驶。");
    int i = new Random().nextInt(10);
    if (i == 5) {
    System.out.println(carName + "车发现道路坏了,停下来维修,预计需要5秒");
    try {
    Thread.sleep(5000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    System.out.println(carName + "车把道路修好了,各辆车可以继续运行");
    }
    try {
    Thread.sleep(1000);
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    }
    } }
    }