我们提供了一个类:
public class Foo {
public void one() { print("one"); }
public void two() { print("two"); }
public void three() { print("three"); }
}
三个不同的线程将会共用一个 Foo 实例。
线程 A 将会调用 one() 方法
线程 B 将会调用 two() 方法
线程 C 将会调用 three() 方法
请设计修改程序,以确保 two() 方法在 one() 方法之后被执行,three() 方法在 two() 方法之后被执行。
第一种方法 countdownlatch方法
classFoo{
privateCountDownLatch c2=newCountDownLatch(1);
privateCountDownLatch c3=newCountDownLatch(1);
publicFoo(){
}
publicvoidfirst(Runnable printFirst)throwsInterruptedException{
// printFirst.run() outputs "first". Do not change or remove this line.
printFirst.run();
c2.countDown();
}
publicvoidsecond(Runnable printSecond)throwsInterruptedException{
c2.await();
// printSecond.run() outputs "second". Do not change or remove this line.
printSecond.run();
c3.countDown();
}
publicvoidthird(Runnable printThird)throwsInterruptedException{
c3.await();
// printThird.run() outputs "third". Do not change or remove this line.
printThird.run();
}
}

第二种方法 CAS
classFoo{
privateAtomicInteger c2=newAtomicInteger(0);
privateAtomicInteger c3=newAtomicInteger(0);
publicFoo(){
}
publicvoidfirst(Runnable printFirst)throwsInterruptedException{
// printFirst.run() outputs "first". Do not change or remove this line.
printFirst.run();
c2.incrementAndGet();
}
publicvoidsecond(Runnable printSecond)throwsInterruptedException{
// printSecond.run() outputs "second". Do not change or remove this line.
while(c2.get()!=1){}
printSecond.run();
c3.incrementAndGet();
}
publicvoidthird(Runnable printThird)throwsInterruptedException{
// printThird.run() outputs "third". Do not change or remove this line.
while(c3.get()!=1){}
printThird.run();
}
}

第三种方法 信号量
classFoo{
privateSemaphore c2=newSemaphore(0);
privateSemaphore c3=newSemaphore(0);
publicFoo(){
}
publicvoidfirst(Runnable printFirst)throwsInterruptedException{
// printFirst.run() outputs "first". Do not change or remove this line.
printFirst.run();
c2.release();
}
publicvoidsecond(Runnable printSecond)throwsInterruptedException{
// printSecond.run() outputs "second". Do not change or remove this line.
c2.acquire();
printSecond.run();
c3.release();
}
publicvoidthird(Runnable printThird)throwsInterruptedException{
// printThird.run() outputs "third". Do not change or remove this line.
c3.acquire();
printThird.run();
}
}

第四种方法 synchronized方法
classFoo{
privatefinalObject o=newObject();
privateintstate=1;
publicFoo(){
}
publicvoidfirst(Runnable printFirst)throwsInterruptedException{
// printFirst.run() outputs "first". Do not change or remove this line.
synchronized(o) {
printFirst.run();
state=2;
o.notifyAll();
}
}
publicvoidsecond(Runnable printSecond)throwsInterruptedException{
// printSecond.run() outputs "second". Do not change or remove this line.
synchronized(o) {
while(state!=2){
o.wait();
}
printSecond.run();
state=3;
o.notifyAll();
}
}
publicvoidthird(Runnable printThird)throwsInterruptedException{
// printThird.run() outputs "third". Do not change or remove this line.
synchronized(o) {
while(state!=3){
o.wait();
}
printThird.run();
}
}
}

第五种方法 lock方法
classFoo{
privateReentrantLock lock=newReentrantLock();
privateCondition c2=lock.newCondition();
privateCondition c3=lock.newCondition();
privateintstate=1;
publicFoo(){
}
publicvoidfirst(Runnable printFirst)throwsInterruptedException{
// printFirst.run() outputs "first". Do not change or remove this line.
try{
lock.lock();
printFirst.run();
c2.signal();
state=2;
}finally{
lock.unlock();
}
}
publicvoidsecond(Runnable printSecond)throwsInterruptedException{
// printSecond.run() outputs "second". Do not change or remove this line.
try{
lock.lock();
while(state!=2){
c2.await();
}
printSecond.run();
state=3;
c3.signal();
}finally{
lock.unlock();
}
}
publicvoidthird(Runnable printThird)throwsInterruptedException{
// printThird.run() outputs "third". Do not change or remove this line.
try{
lock.lock();
while(state!=3){
c3.await();
}
printThird.run();
}finally{
lock.unlock();
}
}
}

我们提供一个类:
class FooBar {
public void foo() {
for (int i = 0; i < n; i++) {
print("foo");
}
}
public void bar() {
for (int i = 0; i < n; i++) {
print("bar");
}
}
}
两个不同的线程将会共用一个 FooBar 实例。其中一个线程将会调用 foo() 方法,另一个线程将会调用 bar() 方法。
请设计修改程序,以确保 "foobar" 被输出 n 次。
classFooBar{
privateintn;
privateObject lock=newObject();
privateintcount=1;
publicFooBar(intn){
this.n = n;
}
publicvoidfoo(Runnable printFoo)throwsInterruptedException{
for(inti =0; i < n; i++) {
synchronized(lock) {
while(count!=1)lock.wait();
// printFoo.run() outputs "foo". Do not change or remove this line.
printFoo.run();
lock.notifyAll();
count--;
}
}
}
publicvoidbar(Runnable printBar)throwsInterruptedException{
for(inti =0; i < n; i++) {
synchronized(lock) {
while(count!=0)lock.wait();
// printBar.run() outputs "bar". Do not change or remove this line.
printBar.run();
lock.notifyAll();
count++;
}
}
}
}
假设有这么一个类:
class ZeroEvenOdd {
public ZeroEvenOdd(int n) { ... } // 构造函数
public void zero(printNumber) { ... } // 仅打印出 0
public void even(printNumber) { ... } // 仅打印出 偶数
public void odd(printNumber) { ... } // 仅打印出 奇数
}
相同的一个 ZeroEvenOdd 类实例将会传递给三个不同的线程:
线程 A 将调用 zero(),它只输出 0 。
线程 B 将调用 even(),它只输出偶数。
线程 C 将调用 odd(),它只输出奇数。
每个线程都有一个 printNumber 方法来输出一个整数。请修改给出的代码以输出整数序列 010203040506... ,其中序列的长度必须为 2n。
classZeroEvenOdd{
privateintn;
privateSemaphore zero=newSemaphore(1);
privateSemaphore odd=newSemaphore(0);
privateSemaphore even=newSemaphore(0);
publicZeroEvenOdd(intn){
this.n = n;
}
// printNumber.accept(x) outputs "x", where x is an integer.
publicvoidzero(IntConsumer printNumber)throwsInterruptedException{
for(inti=1;i<=n;i++){
zero.acquire();
printNumber.accept(0);
if((i&1)==1){
odd.release();
}else{
even.release();
}
}
}
publicvoideven(IntConsumer printNumber)throwsInterruptedException{
for(inti=2;i<=n;i+=2){
even.acquire();
printNumber.accept(i);
zero.release();
}
}
publicvoidodd(IntConsumer printNumber)throwsInterruptedException{
for(inti=1;i<=n;i+=2) {
odd.release();
printNumber.accept(i);
zero.release();
}
}
}
每次获取一个H,需要释放一个O,O需要获取2个,同时H释放两个
classH2O{
privateSemaphore h=newSemaphore(2);
privateSemaphore o=newSemaphore(0);
publicH2O(){
}
publicvoidhydrogen(Runnable releaseHydrogen)throwsInterruptedException{
// releaseHydrogen.run() outputs "H". Do not change or remove this line.
h.acquire();
releaseHydrogen.run();
o.release();
}
publicvoidoxygen(Runnable releaseOxygen)throwsInterruptedException{
// releaseOxygen.run() outputs "O". Do not change or remove this line.
o.acquire(2);
releaseOxygen.run();
h.release(2);
}
}
编写一个可以从 1 到 n 输出代表这个数字的字符串的程序,但是:
如果这个数字可以被 3 整除,输出 "fizz"。
如果这个数字可以被 5 整除,输出 "buzz"。
如果这个数字可以同时被 3 和 5 整除,输出 "fizzbuzz"。
classFizzBuzz{
privateintn;
privateReentrantLock lock=newReentrantLock();
privateCondition f=lock.newCondition();
privateCondition b=lock.newCondition();
privateCondition fb=lock.newCondition();
privateCondition nc=lock.newCondition();
privatebooleanstate=false;
publicFizzBuzz(intn){
this.n = n;
}
// printFizz.run() outputs "fizz".
publicvoidfizz(Runnable printFizz)throwsInterruptedException{
for(inti=3;i<=n;i+=3){
lock.lock();
try{
if(i %5!=0) {
while(!state){
f.await();
}
printFizz.run();
state=false;
nc.signal();
}
}finally{
lock.unlock();
}
}
}
// printBuzz.run() outputs "buzz".
publicvoidbuzz(Runnable printBuzz)throwsInterruptedException{
for(inti=5;i<=n;i+=5){
lock.lock();
try{
if(i%3!=0){
while(!state){
b.await();
}
printBuzz.run();
state=false;
nc.signal();
}
}finally{
lock.unlock();
}
}
}
// printFizzBuzz.run() outputs "fizzbuzz".
publicvoidfizzbuzz(Runnable printFizzBuzz)throwsInterruptedException{
for(inti=15;i<=n;i+=15){
lock.lock();
try{
while(!state){
fb.await();
}
printFizzBuzz.run();
state=false;
nc.signal();
}finally{
lock.unlock();
}
}
}
// printNumber.accept(x) outputs "x", where x is an integer.
publicvoidnumber(IntConsumer printNumber)throwsInterruptedException{
for(inti=1;i<=n;i++){
lock.lock();
try{
while(state){
nc.await();
}
if(i%3==0&&i%5==0){
fb.signal();
state=true;
}
elseif(i%3==0){
f.signal();
state=true;
}elseif(i%5==0){
b.signal();
state=true;
}else{
printNumber.accept(i);
nc.signal();
}
}finally{
lock.unlock();
}
}
}
}
classDiningPhilosophers{
privateReentrantLock[] locks=newReentrantLock[]{
newReentrantLock(),
newReentrantLock(),
newReentrantLock(),
newReentrantLock(),
newReentrantLock()
};
privateSemaphore eatLimit=newSemaphore(4);
publicDiningPhilosophers(){
}
// call the run() method of any runnable to execute its code
publicvoidwantsToEat(intphilosopher,
Runnable pickLeftFork,
Runnable pickRightFork,
Runnable eat,
Runnable putLeftFork,
Runnable putRightFork)throwsInterruptedException {
intleft=(philosopher+1)%5;
intright=philosopher;
eatLimit.acquire();
locks[left].lock();
locks[right].lock();
pickLeftFork.run();
pickRightFork.run();
eat.run();
putLeftFork.run();
putRightFork.run();
locks[left].unlock();
locks[right].unlock();
eatLimit.release();
}
}