信号量和用java计数

时间:2015-06-06 03:07:49

标签: java count synchronization semaphore

我已经写出了我的代码,标明北向和南向的汽车穿过一条车道桥,但我在计算方面遇到了一些麻烦。

它应该是这样的:汽车正在等待,然后可能是几辆,每次都有一个交叉,每次都在增加。相反,它每次重复相同的三个数字。

我应该以不同的方式声明我的计数,还是我不正确地增加它?我尝试了很多不同的方法,但却找不到真正的问题。

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;

public class SingleLaneBridge {

public static void main(String[] args) {
  final Bridge bridge = new Bridge();

  Thread th1 = new Thread( new Runnable() {

    @Override
    public void run() {
      while(true) {
        Car car = new Car(bridge);
        Thread th = new Thread(car);
        th.start();
        try {
          Thread.sleep(5000);
        } catch (InterruptedException e) {
          // TODO Auto-generated catch block
          e.printStackTrace();
        }
      }
    }
    });

    Thread th2 = new Thread( new Runnable() {

      @Override
      public void run() {
        while(true) {
          Car car = new Car(bridge);
          Thread th = new Thread(car);
          th.start();
          try {
            Thread.sleep(5000);
          } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
          }
        }
      }
      });

      th1.start();
      th2.start();
    }
  }

  class Bridge {
    private final Semaphore semaphore;
    public Bridge() {
    semaphore = new Semaphore(1);
  }
  public void crossBridge(Car car) {
    try {
      System.out.printf("Car %s is trying to cross the bridge.           \n",car.count++);
      semaphore.acquire();
      System.out.printf("Car %s is crossing the bridge. \n",car.count++);
      Thread.sleep(5000);
    } catch(InterruptedException iex) {
      iex.printStackTrace();
    } finally {
      System.out.printf(" Car %s has crossed the bridge. \n",car.count++);
      semaphore.release();
    }
  }
}

class Car implements Runnable {
  int count = 0;
  private String name;
  private Bridge bridge;

  public Car(Bridge bridge) {
    this.bridge = bridge;
  }
  public void run() {
    bridge.crossBridge(this);
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }
}

1 个答案:

答案 0 :(得分:1)

它一次又一次地重复这三个数字的原因是,每次都重新创建Car实例并将计数初始化为0.

为了解决这个问题,请按以下方式定义Car类,以获取原子计数,因为此处涉及多个线程(汽车),

class Car implements Runnable {
    private static AtomicInteger globalCarID = new AtomicInteger(0); 
    int count;
    ...

    public Car(Bridge bridge) {
        this.bridge = bridge;
        count = globalCarID.incrementAndGet();
    }
}

并修改crossBridge()方法中的System.out.printf以不增加计数,

以下是可能提供您想要的完整代码,

import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

public class SingleLaneBridge {

    public static void main(String[] args) {
        final Bridge bridge = new Bridge();

        Thread th1 = new Thread( new Runnable() {

        public void run() {
            while(true) {
                Car car = new Car(bridge);
                Thread th = new Thread(car);
                th.start();
                try {
                  Thread.sleep(5000);
                } catch (InterruptedException e) {
                  // TODO Auto-generated catch block
                  e.printStackTrace();
                }
            }
        }
        });

        Thread th2 = new Thread( new Runnable() {

        public void run() {
            while(true) {
                Car car = new Car(bridge);
                Thread th = new Thread(car);
                th.start();
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        });

        th1.start();
        th2.start();
    }
}

class Bridge {
    private final Semaphore semaphore;
    public Bridge() {
        semaphore = new Semaphore(1);
    }

    public void crossBridge(Car car) {
        try {
            System.out.printf("Car %s is trying to cross the bridge. \n",car.count);
            semaphore.acquire();
            System.out.printf("Car %s is crossing the bridge. \n",car.count);
            Thread.sleep(500);
        } catch(InterruptedException iex) {
            iex.printStackTrace();
        } finally {
            System.out.printf(" Car %s has crossed the bridge. \n",car.count);
            semaphore.release();
        }
    }
}   

class Car implements Runnable {
    private static AtomicInteger globalCarID = new AtomicInteger(0); 
    int count;
    private String name;
    private Bridge bridge;

    public Car(Bridge bridge) {
        this.bridge = bridge;
        count = globalCarID.incrementAndGet();
    }

    public void run() {
        bridge.crossBridge(this);
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}