Phaser
1.arriveAndAwaitAdvance()方法
1 package Three_Phaser_arriveAndDeregister; 2 3 import java.util.concurrent.Phaser; 4 5 public class Service { 6 7 Phaser phaser; 8 9 public Service(Phaser phaser) { 10 super(); 11 this.phaser = phaser; 12 } 13 14 public void methodA() throws InterruptedException { 15 System.out.println(Thread.currentThread().getName() + "赛程1 开始!!" + System.currentTimeMillis()); 16 phaser.arriveAndAwaitAdvance(); 17 System.out.println(Thread.currentThread().getName() + "赛程1 结束!!" + System.currentTimeMillis()); 18 19 } 20 21 }
1 package Three_Phaser_arriveAndDeregister; 2 3 import java.util.concurrent.Phaser; 4 5 public class ThreadA extends Thread { 6 7 private Service service; 8 9 public ThreadA(Service service) { 10 super(); 11 this.service = service; 12 } 13 14 public void run() { 15 try { 16 service.methodA(); 17 } catch (InterruptedException e) { 18 // TODO Auto-generated catch block 19 e.printStackTrace(); 20 } 21 } 22 } 23 ----------------------------------------------------------------------------------------- 24 package Three_Phaser_arriveAndDeregister; 25 26 import java.util.concurrent.Phaser; 27 28 public class ThreadB extends Thread { 29 30 private Service service; 31 32 public ThreadB(Service service) { 33 super(); 34 this.service = service; 35 } 36 37 public void run() { 38 try { 39 service.methodA(); 40 } catch (InterruptedException e) { 41 // TODO Auto-generated catch block 42 e.printStackTrace(); 43 } 44 } 45 } 46 ----------------------------------------------------------------------------------------- 47 package Three_Phaser_arriveAndDeregister; 48 49 import java.util.concurrent.Phaser; 50 51 public class ThreadC extends Thread { 52 53 private Service service; 54 55 public ThreadC(Service service) { 56 super(); 57 this.service = service; 58 } 59 60 public void run() { 61 try { 62 service.methodA(); 63 } catch (InterruptedException e) { 64 // TODO Auto-generated catch block 65 e.printStackTrace(); 66 } 67 } 68 }
1 package Three_Phaser_arriveAndDeregister; 2 3 import java.util.concurrent.Phaser; 4 5 public class Run { 6 public static void main(String[] args) { 7 Phaser phaser = new Phaser(2); 8 Service service = new Service(phaser); 9 10 ThreadA a = new ThreadA(service); 11 a.setName("A"); 12 13 ThreadB b = new ThreadB(service); 14 b.setName("B"); 15 16 ThreadC c = new ThreadC(service); 17 c.setName("C"); 18 19 a.start(); 20 b.start(); 21 c.start(); 22 } 23 24 }
Phaser phaser = new Phaser(2);这里将参数设置成2(设置了2个parties),即等待两个线程同时到阻塞点后,再继续进行后面的程序,如果线程的数量大于参数的数量,则是两两为一组,到达阻塞点后再继续进行后序程序。
而这里设置了3个线程,所以,只有其中的两个线程可以组合成功后继续下面的程序,而另外那个一个线程,将会被堵到阻塞点这里。

2.arriveAndAwaitDeregister()方法
如果Phaser phaser = new Phaser(3),这里设置了3个parties,此时正有3个线程运行,倘若中途有一个线程退出,那么其他两个线程将会被永远堵在阻塞点处,此时,使用arriveAndAwaitDeregister()方法,那么带来的效果就是parties会执行减1的操作,此时,堵在阻塞点的那辆线程就可以继续往下执行。
1 package Three_Phaser_arriveAndDeregister; 2 3 import java.util.concurrent.Phaser; 4 5 public class Service { 6 7 Phaser phaser; 8 9 public Service(Phaser phaser) { 10 super(); 11 this.phaser = phaser; 12 } 13 14 public void methodA() throws InterruptedException { 15 System.out.println(Thread.currentThread().getName() + "赛程1 开始!!" + System.currentTimeMillis()); 16 phaser.arriveAndAwaitAdvance(); 17 System.out.println(Thread.currentThread().getName() + "赛程1 结束!!" + System.currentTimeMillis()); 18 19 Thread.sleep(5000); 20 System.out.println(Thread.currentThread().getName() + "赛程2 开始!!" + System.currentTimeMillis()); 21 phaser.arriveAndAwaitAdvance(); 22 System.out.println(Thread.currentThread().getName() + "赛程2 结束!!" + System.currentTimeMillis()); 23 24 } 25 26 27 28 public void methodC() throws InterruptedException { 29 System.out.println(Thread.currentThread().getName() + "赛程1 开始!!" + System.currentTimeMillis()); 30 Thread.sleep(5000); 31 phaser.arriveAndAwaitAdvance(); 32 System.out.println(Thread.currentThread().getName() + "赛程1 结束!!" + System.currentTimeMillis()); 33 Thread.sleep(5000); 34 System.out.println(Thread.currentThread().getName()+"退出比赛!!!"); 35 phaser.arriveAndDeregister();//使parties减1 36 /* 37 System.out.println(Thread.currentThread().getName() + "赛程2 开始!!" + System.currentTimeMillis()); 38 Thread.sleep(5000); 39 phaser.arriveAndAwaitAdvance(); 40 System.out.println(Thread.currentThread().getName() + "赛程2 结束!!" + System.currentTimeMillis()); 41 */ 42 } 43 44 }
package Three_Phaser_arriveAndDeregister; import java.util.concurrent.Phaser; public class ThreadA extends Thread { private Service service; public ThreadA(Service service) { super(); this.service = service; } public void run() { try { service.methodA(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } ----------------------------------------------------------------------------------------- package Three_Phaser_arriveAndDeregister; import java.util.concurrent.Phaser; public class ThreadB extends Thread { private Service service; public ThreadB(Service service) { super(); this.service = service; } public void run() { try { service.methodA(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } ----------------------------------------------------------------------------------------- package Three_Phaser_arriveAndDeregister; import java.util.concurrent.Phaser; public class ThreadC extends Thread { private Service service; public ThreadC(Service service) { super(); this.service = service; } public void run() { try { service.methodC(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
1 package Three_Phaser_arriveAndDeregister; 2 3 import java.util.concurrent.Phaser; 4 5 public class Run { 6 public static void main(String[] args) { 7 Phaser phaser = new Phaser(3); 8 Service service = new Service(phaser); 9 10 ThreadA a = new ThreadA(service); 11 a.setName("A"); 12 13 ThreadB b = new ThreadB(service); 14 b.setName("B"); 15 16 ThreadC c = new ThreadC(service); 17 c.setName("C"); 18 19 a.start(); 20 b.start(); 21 c.start(); 22 } 23 24 }
运行结果:

可以看到,虽然C线程中途退出,但是由于执行了arriveAndDeregister()方法,使得parties的数量由3减为2,所以,只需要凑够2个线程就可以越过阻塞点,结果表现为,其他两个线程越过阻塞点,顺利执行下面的程序。
3. arrive()方法
使parties的值-1,同时getArrivedParties()的值即已使用parties的值+1,并且使线程越过当前屏障点(越过后如果使用getPhase()方法来获取越过屏障的值,会发现,越过屏障值+1),继续进行下面的代码
(1)
1 package Tree_Phaser_arrive3; 2 3 import java.util.concurrent.Phaser; 4 5 public class Service { 6 Phaser phaser; 7 8 public Service(Phaser phaser) { 9 super(); 10 this.phaser = phaser; 11 } 12 13 public void methodA() throws InterruptedException { 14 System.out.println(Thread.currentThread().getName() + "赛程1 开始" + System.currentTimeMillis()); 15 Thread.sleep(3000); 16 phaser.arriveAndAwaitAdvance(); 17 System.out.println(Thread.currentThread().getName() + "赛程1 结束" + System.currentTimeMillis()); 18 } 19 20 public void methodB() { 21 System.out.println(Thread.currentThread().getName() + "赛程1 开始" + System.currentTimeMillis()); 22 phaser.arrive(); 23 System.out.println(Thread.currentThread().getName() + "赛程1 结束" + System.currentTimeMillis()); 24 } 25 }
1 package Tree_Phaser_arrive3; 2 3 public class ThreadA extends Thread { 4 5 private Service s; 6 7 public ThreadA(Service s) { 8 super(); 9 this.s = s; 10 } 11 12 public void run() { 13 14 try { 15 s.methodA(); 16 } catch (InterruptedException e) { 17 // TODO Auto-generated catch block 18 e.printStackTrace(); 19 } 20 } 21 22 } 23 ----------------------------------------------------------------------------------------- 24 package Tree_Phaser_arrive3; 25 26 public class ThreadB extends Thread { 27 28 private Service s; 29 30 public ThreadB(Service s) { 31 super(); 32 this.s = s; 33 } 34 35 public void run() { 36 37 try { 38 s.methodA(); 39 } catch (InterruptedException e) { 40 // TODO Auto-generated catch block 41 e.printStackTrace(); 42 } 43 } 44 45 } 46 ----------------------------------------------------------------------------------------- 47 package Tree_Phaser_arrive3; 48 49 public class ThreadC extends Thread { 50 51 private Service s; 52 53 public ThreadC(Service s) { 54 super(); 55 this.s = s; 56 } 57 58 public void run() { 59 60 s.methodB(); 61 62 } 63 64 }
1 package Tree_Phaser_arrive3; 2 3 import java.util.concurrent.Phaser; 4 5 public class Run { 6 public static void main(String[] args) { 7 Phaser phaser = new Phaser(3); 8 Service s = new Service(phaser); 9 10 ThreadA a = new ThreadA(s); 11 a.setName("A"); 12 ThreadB b = new ThreadB(s); 13 b.setName("B"); 14 ThreadC c = new ThreadC(s); 15 c.setName("C"); 16 a.start(); 17 b.start(); 18 c.start(); 19 } 20 21 }
运行结果:

分析:
这里总共设置了3个parties,而只有线程A和线程B的方法中使用了arriveAndAwaitAdvance()方法,分别使parties的数量减1,剩下1个parties,然后A、B就被堵在阻塞点了,而线程C中使用的是arrive()的方法,使用后线程C接着往下执行,parties的值减1此时partiesd的值为,然后线程A、B就可以越过屏障点,继续向下执行。
如果这里将parties的值设为4,则A、B执行完arriveAndAwaitAdvance()方法后,parties的值为2,A、B就被堵在阻塞点,而C通过执行arrive()越过当前阻塞点,并使parties的值减了1,可是当前parties的值为1,所以还需要一个操作来将其减为0后A、B才可以通过当前阻塞点,所以带来的结果就是:C顺利通过阻塞点,而A、B任然被堵在阻塞点。

(2)
1 package Three_Phaser_arrive; 2 3 import java.util.concurrent.Phaser; 4 /* 5 * 全程没有执行arriveAndAwaitAdvance()方法!!! 6 */ 7 public class Run { 8 public static void main(String[] argd) { 9 Phaser phaser = new Phaser(2) { 10 protected boolean onAdvance(int phase, int registeredParties) { 11 System.out.println("onAdvance()方法被调用"); 12 return false; 13 } 14 }; 15 16 System.out.println("A1 getPhase(越过的屏障): " + phaser.getPhase() + " getRegisteredParties(注册的parties数量): " 17 + phaser.getRegisteredParties() + " getArrivedParties(已经使用的parties数量): " + phaser.getArrivedParties()); 18 19 phaser.arrive();//使parties的值+1,并且越过当前屏障(这时会使得getPhase的值+1,即越过的屏障数+1)向下面运行 20 21 System.out.println("A1 getPhase(越过的屏障): " + phaser.getPhase() + " getRegisteredParties(注册的parties数量): " 22 + phaser.getRegisteredParties() + " getArrivedParties(已经使用的parties数量): " + phaser.getArrivedParties()); 23 24 System.out.println("A2 getPhase(越过的屏障): " + phaser.getPhase() + " getRegisteredParties(注册的parties数量): " 25 + phaser.getRegisteredParties() + " getArrivedParties(已经使用的parties数量): " + phaser.getArrivedParties()); 26 27 phaser.arrive();//使parties的值+1,并且越过当前屏障,向下面运行 28 29 System.out.println("A2 getPhase(越过的屏障): " + phaser.getPhase() + " getRegisteredParties(注册的parties数量): " 30 + phaser.getRegisteredParties() + " getArrivedParties(已经使用的parties数量): " + phaser.getArrivedParties()); 31 32 ////////////////////////////////////////////////// 33 System.out.println("B1 getPhase(越过的屏障): " + phaser.getPhase() + " getRegisteredParties(注册的parties数量): " 34 + phaser.getRegisteredParties() + " getArrivedParties(已经使用的parties数量): " + phaser.getArrivedParties()); 35 36 phaser.arrive();//使parties的值+1,并且越过当前屏障,向下面运行 37 38 System.out.println("B1 getPhase(越过的屏障): " + phaser.getPhase() + " getRegisteredParties(注册的parties数量): " 39 + phaser.getRegisteredParties() + " getArrivedParties(已经使用的parties数量): " + phaser.getArrivedParties()); 40 41 System.out.println("B2 getPhase(越过的屏障): " + phaser.getPhase() + " getRegisteredParties(注册的parties数量): " 42 + phaser.getRegisteredParties() + " getArrivedParties(已经使用的parties数量): " + phaser.getArrivedParties()); 43 44 phaser.arrive();//使parties的值+1,并且越过当前屏障,向下面运行 45 46 System.out.println("B2 getPhase(越过的屏障): " + phaser.getPhase() + " getRegisteredParties(注册的parties数量): " 47 + phaser.getRegisteredParties() + " getArrivedParties(已经使用的parties数量): " + phaser.getArrivedParties()); 48 49 50 //////////////////////////////////////////////////// 51 System.out.println("C1 getPhase(越过的屏障): " + phaser.getPhase() + " getRegisteredParties(注册的parties数量): " 52 + phaser.getRegisteredParties() + " getArrivedParties(已经使用的parties数量): " + phaser.getArrivedParties()); 53 54 phaser.arrive();//使parties的值+1,并且越过当前屏障,向下面运行 55 56 System.out.println("C1 getPhase(越过的屏障): " + phaser.getPhase() + " getRegisteredParties(注册的parties数量): " 57 + phaser.getRegisteredParties() + " getArrivedParties(已经使用的parties数量): " + phaser.getArrivedParties()); 58 59 System.out.println("C2 getPhase(越过的屏障): " + phaser.getPhase() + " getRegisteredParties(注册的parties数量): " 60 + phaser.getRegisteredParties() + " getArrivedParties(已经使用的parties数量): " + phaser.getArrivedParties()); 61 62 phaser.arrive();//使parties的值+1,并且越过当前屏障,向下面运行 63 64 System.out.println("C2 getPhase(越过的屏障): " + phaser.getPhase() + " getRegisteredParties(注册的parties数量): " 65 + phaser.getRegisteredParties() + " getArrivedParties(已经使用的parties数量): " + phaser.getArrivedParties()); 66 67 68 69 } 70 71 }
运行结果:

代码中没有写arriveAndAwaitAdvance()方法,所以说,这里没有通过之前的互相等待的方式,即让与parties值数量相同的线程执行arriveAndAwaitAdvance()方法,达到消除当前屏障,共同越过屏障的效果。
这里使用arrive()方法,使得当前线程越过屏障,而这种arrive()方法带来的效果对于getPhase()的值和onAdvance()的行为的影响和之前使用arriveAndAwaitAdvance()方法是一样的。即:使用arrive()方法越过屏障和使用arriveAndAwaitAdvance()使parties的值减为0然后越过屏障,都会被认为是成功越过当前屏障,都会使得getPhase()的值增加;使用两者越过屏障后都会触发onAdvance()方法的执行。
4. awaitAdvance(int phase)方法
传入参数phase的值和当前getPhase()方法返回值相同时,调用这个方法的线程将在阻塞点处等待,否则继续进行下面的程序。
1 package Three_Phaser_awaitAdvance; 2 3 import java.util.concurrent.Phaser; 4 5 public class ThreadA extends Thread { 6 7 private Phaser phaser; 8 9 public ThreadA(Phaser phaser) { 10 super(); 11 this.phaser = phaser; 12 } 13 14 public void run() { 15 System.out.println(Thread.currentThread().getName() + "A1 begin" + System.currentTimeMillis()); 16 phaser.arriveAndAwaitAdvance(); 17 System.out.println(Thread.currentThread().getName() + "A1 end" + System.currentTimeMillis()); 18 } 19 } 20 -------------------------------------------------------------------------------------------- 21 package Three_Phaser_awaitAdvance; 22 23 import java.util.concurrent.Phaser; 24 25 public class ThreadB extends Thread { 26 27 private Phaser phaser; 28 29 public ThreadB(Phaser phaser) { 30 super(); 31 this.phaser = phaser; 32 } 33 34 public void run() { 35 System.out.println(Thread.currentThread().getName() + "A1 begin" + System.currentTimeMillis()); 36 phaser.arriveAndAwaitAdvance(); 37 System.out.println(Thread.currentThread().getName() + "A1 end" + System.currentTimeMillis()); 38 } 39 } 40 ----------------------------------------------------------------------------------------- 41 package Three_Phaser_awaitAdvance; 42 43 import java.util.concurrent.Phaser; 44 45 public class ThreadC extends Thread { 46 47 private Phaser phaser; 48 49 public ThreadC(Phaser phaser) { 50 super(); 51 this.phaser = phaser; 52 } 53 54 public void run() { 55 try { 56 Thread.sleep(2000); 57 } catch (InterruptedException e) { 58 // TODO Auto-generated catch block 59 e.printStackTrace(); 60 } 61 System.out.println(Thread.currentThread().getName() + "A1 begin" + System.currentTimeMillis()); 62 System.out.println("已经越过的阻塞点个数: " + phaser.getPhase()); 63 phaser.awaitAdvance(0); 64 System.out.println(Thread.currentThread().getName() + "A1 end" + System.currentTimeMillis()); 65 } 66 } 67 ----------------------------------------------------------------------------------------- 68 package Three_Phaser_awaitAdvance; 69 70 import java.util.concurrent.Phaser; 71 72 public class ThreadD extends Thread { 73 74 private Phaser phaser; 75 76 public ThreadD(Phaser phaser) { 77 super(); 78 this.phaser = phaser; 79 } 80 81 public void run() { 82 try { 83 Thread.sleep(5000); 84 } catch (InterruptedException e) { 85 // TODO Auto-generated catch block 86 e.printStackTrace(); 87 } 88 System.out.println(Thread.currentThread().getName() + "A1 begin" + System.currentTimeMillis()); 89 phaser.arriveAndAwaitAdvance(); 90 System.out.println(Thread.currentThread().getName() + "A1 end" + System.currentTimeMillis()); 91 } 92 }
1 package Three_Phaser_awaitAdvance; 2 3 import java.util.concurrent.Phaser; 4 5 public class Run { 6 public static void main(String[] args) { 7 Phaser phaser = new Phaser(3); 8 9 ThreadA a = new ThreadA(phaser); 10 a.setName("A"); 11 12 ThreadB b = new ThreadB(phaser); 13 b.setName("B"); 14 15 ThreadC c = new ThreadC(phaser); 16 c.setName("C"); 17 18 ThreadD d = new ThreadD(phaser); 19 d.setName("D"); 20 21 a.start(); 22 b.start(); 23 c.start(); 24 d.start(); 25 } 26 27 }
运行结果:

分析:
当前设置的参数为0,可以看到,在C线程中,通过getPhase()返回的值为0,与awaitAdvance(0)中传入的参数相同,此时线程C进入等待,而线程A、B还没有越过阻塞点,这也就是getPhase()返回值为0的原因,当D线程执行arriveAndAwaitAdvance()方法,将praties的值减为0时,A、B、D同时越过阻塞点,这个时候越过阻塞点的线程的数目为3,即此时getPhase()返回值为3,与awaitAdvance(0)中传入的参数0不同,此时线程C继续向下执行。
如将参数改为3,即awaitAdvance(3),则C线程将先越过阻塞点继续执行
1 package Three_Phaser_awaitAdvance; 2 3 import java.util.concurrent.Phaser; 4 5 public class ThreadC extends Thread { 6 7 private Phaser phaser; 8 9 public ThreadC(Phaser phaser) { 10 super(); 11 this.phaser = phaser; 12 } 13 14 public void run() { 15 try { 16 Thread.sleep(2000); 17 } catch (InterruptedException e) { 18 // TODO Auto-generated catch block 19 e.printStackTrace(); 20 } 21 System.out.println(Thread.currentThread().getName() + "A1 begin" + System.currentTimeMillis()); 22 System.out.println("已经越过的阻塞点个数: " + phaser.getPhase()); 23 phaser.awaitAdvance(3);//将传入的参数由0改为3 24 System.out.println(Thread.currentThread().getName() + "A1 end" + System.currentTimeMillis()); 25 } 26 }
运行结果:

注:awaitAdvance(int Phase)并不参与parties计数操作,仅仅具有判断的功能。
(3)awaitAdvance(int Phase)在等待的时候,即当getPhase()的返回值与awaitAdvance(int Phase)中传递的参数不同时,线程处于等待状态中,这个时候如果有中断的话,线程状态不受影响,依旧会处于等待中。即不可中断
1 package Three_Phaser_awaitAdvance2; 2 3 import java.util.concurrent.Phaser; 4 5 public class MyThread extends Thread{ 6 private Phaser phaser; 7 8 public MyThread(Phaser phaser) { 9 super(); 10 this.phaser = phaser; 11 } 12 13 public void run(){ 14 System.out.println(Thread.currentThread().getName()+" begin"+System.currentTimeMillis()); 15 phaser.awaitAdvance(0); 16 System.out.println(Thread.currentThread().getName()+" end"+System.currentTimeMillis()); 17 18 } 19 20 21 }
1 package Three_Phaser_awaitAdvance2; 2 3 import java.util.concurrent.Phaser; 4 5 public class Run { 6 public static void main(String[] args) throws InterruptedException{ 7 Phaser phaser=new Phaser(3); 8 MyThread mt=new MyThread(phaser); 9 mt.setName("A"); 10 mt.start(); 11 Thread.sleep(5000); 12 mt.interrupt();//产生一个中断 13 System.out.println("中断"); 14 } 15 16 }
运行结果:

分析:
可以看到,中断并没有影响线程A的继续等待,即虽然来了一个中断,但是线程A还是停在awaitAdvance(0)那里。
(4)awaitAdvanceInterruptibly(int Phaser)
这个方法是可中断的,即,当线程停在awaitAdvanceInterruptibly(int Phaser)时,若进来一个中断,则线程就会被中断。

浙公网安备 33010602011771号