Java并发编程:核心方法与框架
上QQ阅读APP看书,第一时间看更新

1.1.7 公平与非公平信号量的测试

有些时候,获得许可的顺序与线程启动的顺序有关,这时信号量就要分为公平与非公平的。

所谓的公平信号量是获得锁的顺序与线程启动的顺序有关,但不代表100%地获得信号量,仅仅是在概率上能得到保证。而非公平信号量就是无关的了。

创建测试用的项目semaphoreFairTest,类MyService.java代码如下:


        package myservice;
        import java.util.concurrent.Semaphore;
        public class MyService {
        private boolean isFair = false;
        private Semaphore semaphore = new Semaphore(1, isFair);
        public void testMethod() {
            try {
                semaphore.acquire();
                System.out
                        .println("ThreadName=" + Thread.currentThread().getName());
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                semaphore.release();
            }
        }
    }

类MyThread.java代码如下:


    package extthread;
    import myservice.MyService;
    public class MyThread extends Thread {
        private MyService myService;
        public MyThread(MyService myService) {
            super();
            this.myService = myService;
        }
        @Override
        public void run() {
            System.out.println("ThreadName=" + this.getName() + "启动了!");
            myService.testMethod();
        }
    }

类Run.java代码如下:


    package test.run;
    import myservice.MyService;
    import extthread.MyThread;
    public class Run {
        public static void main(String[] args) {
            MyService service = new MyService();
            MyThread firstThread = new MyThread(service);
            firstThread.start();
                  MyThread[] threadArray = new MyThread[4];
                  for (int i = 0; i < 4; i++) {
                      threadArray[i] = new MyThread(service);
                      threadArray[i].start();
                  }
              }
          }

程序运行后的效果如图1-15所示。

图1-15 乱序打印

非公平信号量运行的效果是线程启动的顺序与调用semaphore.acquire()的顺序无关,也就是线程先启动了并不代表先获得许可。

更改MyService.java类代码如下:


        private boolean isFair = true;

程序运行结果如图1-16所示。

图1-16 有序打印

公平信号量运行的效果是线程启动的顺序与调用semaphore.acquire()的顺序有关,也就是先启动的线程优先获得许可。