30-案例实现
案例实现
根据以下步骤实现本案例。
1.创建类型为 Position
的共享对象,该类包含 x
和 y
两个属性,并且给它们都配备相应的 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
类,并在该类中尝试读取共享对象的值。该类包含两个属性:名为 position
的 Position
对象和类型为 lock
的 StampedLock
对象,并在构造函数中完成初始化:
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
任务。该类包含两个属性:名为 position
的 Position
对象和名为 lock
的 StampedLock
对象,并在构造函数中完成这两个属性的初始化工作:
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()
方法。在该方法中创建 Position
和 StampedLock
对象实例,并为这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();
}
}
}