当前位置:嗨网首页>书籍在线阅读

30-案例实现

  
选择背景色: 黄橙 洋红 淡粉 水蓝 草绿 白色 选择字体: 宋体 黑体 微软雅黑 楷体 选择字体大小: 恢复默认

案例实现

根据以下步骤实现本案例。

1.创建类型为 Position 的共享对象,该类包含 xy 两个属性,并且给它们都配备相应的 get()set() 方法。代码比较简单,此处就不再展示了。

2.创建实现 Runnable 接口的 Writer 任务。该类中包含类型为 Position 对象实例和类型为 StampedLock 且名为 lock 的对象实例,并在构造函数中完成初始化操作:

public class Writer implements Runnable {
 private final Position position;
 private final StampedLock lock;
 public Writer (Position position, StampedLock lock) {
   this.position=position;
   this.lock=lock;
 }

3.实现 run() 方法,并在方法中执行10次以下步骤:以写模式获得锁,分别修改对象实例 position 上的两个属性并把当前线程暂停1s,释放锁(在 try...catch... finally 结构的 finally 代码块中完成),最后暂停1s当前线程:

@Override
public void run() {
  for (int i=0; i<10; i++) {
    long stamp = lock.writeLock();
    try {
      System.out.printf("Writer: Lock acquired %d\n",stamp);
      position.setX(position.getX()+1);
      position.setY(position.getY()+1);
      TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
      e.printStackTrace();
    } finally {
      lock.unlockWrite(stamp);
      System.out.printf("Writer: Lock released %d\n",stamp);
    }
    try {
      TimeUnit.SECONDS.sleep(1);
    } catch (InterruptedException e) {
      e.printStackTrace();
    } 
  }
}

4.实现一个 Runnable 接口的 Reader 类,并在该类中尝试读取共享对象的值。该类包含两个属性:名为 positionPosition 对象和类型为 lockStampedLock 对象,并在构造函数中完成初始化:

public class Reader implements Runnable { 
  private final Position position;
  private final StampedLock lock;
  public Reader (Position position, StampedLock lock) {
    this.position=position;
    this.lock=lock;
  }

5.实现 run() 方法,并在该方法中循环执行以下动作50次,以读模式获得锁,将当前的 position 值输出到控制台中,在 try...catch...finally 结构的 finally 代码块内释放锁:

@Override
public void run() {
  for (int i=0; i<50; i++) {
    long stamp=lock.readLock();
    try {
      System.out.printf("Reader: %d - (%d,%d)\n", stamp,
                        position.getX(), position.getY());
      TimeUnit.MILLISECONDS.sleep(200);
    } catch (InterruptedException e) {
      e.printStackTrace();
    } finally {
      lock.unlockRead(stamp);
      System.out.printf("Reader: %d - Lock released\n", stamp);
    }
  }
}

6.实现 Runnable 接口的 OptimisticReader 任务。该类包含两个属性:名为 positionPosition 对象和名为 lockStampedLock 对象,并在构造函数中完成这两个属性的初始化工作:

public class OptimisticReader implements Runnable {
  private final Position position;
  private final StampedLock lock;
  public OptimisticReader (Position position, StampedLock lock) {
    this.position=position;
    this.lock=lock;
  }

7.实现 run() 方法,并在该方法中循环执行以下步骤100次:通过 tryOptimisticRead() 以乐观读的模式获得锁的票据,通过 validate() 方法检查线程当前是否已获取数据,如果返回值为 true ,则将输出位置信息到控制台上,否则输出其他信息到控制台上,这时再次尝试通过 tryOptimisticRead() 获得其他票据信息,最后整个线程暂停200ms:

@Override
public void run() {
  long stamp;
  for (int i=0; i<100; i++) {
    try {
      stamp=lock.tryOptimisticRead();
      int x = position.getX();
      int y = position.getY();
      if (lock.validate(stamp)) {
        System.out.printf("OptmisticReader: %d - (%d,%d)\n",
                          stamp,x, y);
      } else {
        System.out.printf("OptmisticReader: %d - Not Free\n",
                          stamp);
      }
      TimeUnit.MILLISECONDS.sleep(200);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}

8.创建一个 Main 类,并且在该类中添加用于执行本例代码的 main() 方法。在该方法中创建 PositionStampedLock 对象实例,并为这3种任务中的每个都搭配一个执行线程,最后在主线程中等待3个任务执行完成:

public class Main {
  public static void main(String[] args) {
    Position position=new Position();
    StampedLock lock=new StampedLock();
    Thread threadWriter=new Thread(new Writer(position,lock));
    Thread threadReader=new Thread(new Reader(position, lock));
    Thread threadOptReader=new Thread(new OptimisticReader
                                       (position, lock));
    threadWriter.start();
    threadReader.start();
    threadOptReader.start();
    try {
      threadWriter.join();
      threadReader.join();
      threadOptReader.join();
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
  }
}