• Java并发编程核心方法与框架-phaser的使用


    arriveAndAwaitAdvance()方法

    arriveAndAwaitAdvance()作用是当前线程已经到达屏障,在此等待一段时间,等条件满足后继续向下一个屏障执行。

    public class PrintTools {
    	public static Phaser phaser;
    	public static void methodA() {
    		System.out.println(Thread.currentThread().getName() + " A1 begin " + System.currentTimeMillis());
    		phaser.arriveAndAwaitAdvance();
    		System.out.println(Thread.currentThread().getName() + " A1 end " + System.currentTimeMillis());
    		System.out.println(Thread.currentThread().getName() + " A2 begin " + System.currentTimeMillis());
    		phaser.arriveAndAwaitAdvance();
    		System.out.println(Thread.currentThread().getName() + " A2 end " + System.currentTimeMillis());
    	}
    	
    	public static void methodB() {
    		try {
    			System.out.println(Thread.currentThread().getName() + " A1 begin " + System.currentTimeMillis());
    			Thread.sleep(5000);
    			phaser.arriveAndAwaitAdvance();
    			System.out.println(Thread.currentThread().getName() + " A1 end " + System.currentTimeMillis());
    			System.out.println(Thread.currentThread().getName() + " A2 begin " + System.currentTimeMillis());
    			Thread.sleep(5000);
    			phaser.arriveAndAwaitAdvance();
    			System.out.println(Thread.currentThread().getName() + " A2 end " + System.currentTimeMillis());
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    }
    
    public class ThreadA extends Thread {
    	@Override
    	public void run() {
    		PrintTools.methodA();//执行A方法
    	}
    }
    
    public class ThreadB extends Thread {
    	@Override
    	public void run() {
    		PrintTools.methodA();//执行A方法
    	}
    }
    
    public class ThreadC extends Thread {
    	@Override
    	public void run() {
    		PrintTools.methodB();//执行B方法
    	}
    }
    
    public class Main {
    	public static void main(String[] args) {
    		Phaser phaser = new Phaser(3);
    		PrintTools.phaser = phaser;
    		ThreadA a = new ThreadA();
    		a.setName("A");
    		a.start();
    		ThreadB b = new ThreadB();
    		b.setName("B");
    		b.start();
    		ThreadC c = new ThreadC();
    		c.setName("C");
    		c.start();
    	}
    }
    

    程序运行结果如下:

    A A1 begin 1469711023742
    B A1 begin 1469711023742
    C A1 begin 1469711023743
    C A1 end 1469711028745
    A A1 end 1469711028745
    B A1 end 1469711028745
    A A2 begin 1469711028745
    C A2 begin 1469711028745
    B A2 begin 1469711028745
    B A2 end 1469711033748
    C A2 end 1469711033748
    A A2 end 1469711033748
    

    A、B线程会等待C线程一起到达屏障点,然后一起继续向下执行。

    对以上代码做如下修改:

    public class PrintTools {
    	public static Phaser phaser;
    	public static void methodA() {
    		System.out.println(Thread.currentThread().getName() + " A1 begin " + System.currentTimeMillis());
    		phaser.arriveAndAwaitAdvance();
    		System.out.println(Thread.currentThread().getName() + " A1 end " + System.currentTimeMillis());
    		System.out.println(Thread.currentThread().getName() + " A2 begin " + System.currentTimeMillis());
    		phaser.arriveAndAwaitAdvance();
    		System.out.println(Thread.currentThread().getName() + " A2 end " + System.currentTimeMillis());
    	}
    	
    	public static void methodB() {
    		try {
    			System.out.println(Thread.currentThread().getName() + " A1 begin " + System.currentTimeMillis());
    			Thread.sleep(5000);
    			phaser.arriveAndAwaitAdvance();
    			System.out.println(Thread.currentThread().getName() + " A1 end " + System.currentTimeMillis());
    			/* C提前退出比赛
    			System.out.println(Thread.currentThread().getName() + " A2 begin " + System.currentTimeMillis());
    			Thread.sleep(5000);
    			phaser.arriveAndAwaitAdvance();
    			System.out.println(Thread.currentThread().getName() + " A2 end " + System.currentTimeMillis());
    			*/
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    }
    //其他代码保持不变
    

    重新运行程序,控制台打印结果如下:

    A A1 begin 1469711274416
    B A1 begin 1469711274416
    C A1 begin 1469711274417
    B A1 end 1469711279421
    C A1 end 1469711279421
    A A1 end 1469711279421
    B A2 begin 1469711279421
    A A2 begin 1469711279421
    

    A、B到达第二个屏障点后等不到C的到来,程序不结束,将会一直等下去。


    arriveAndDeregister()方法

    arriveAndDeregister()方法的作用是使线程退出比赛,并且使parties值减1

    对以上代码做如下修改:

    public class PrintTools {
    	public static Phaser phaser;
    	public static void methodA() {
    		System.out.println(Thread.currentThread().getName() + " A1 begin " + System.currentTimeMillis());
    		phaser.arriveAndAwaitAdvance();
    		System.out.println(Thread.currentThread().getName() + " A1 end " + System.currentTimeMillis());
    		System.out.println(Thread.currentThread().getName() + " A2 begin " + System.currentTimeMillis());
    		phaser.arriveAndAwaitAdvance();
    		System.out.println(Thread.currentThread().getName() + " A2 end " + System.currentTimeMillis());
    	}
    	
    	public static void methodB() {
    		try {
    			System.out.println(Thread.currentThread().getName() + " A1 begin " + System.currentTimeMillis());
    			Thread.sleep(5000);
    			System.out.println("A:" + phaser.getRegisteredParties());
    			phaser.arriveAndDeregister();//退出比赛
    			System.out.println("B:" + phaser.getRegisteredParties());
    			System.out.println(Thread.currentThread().getName() + " A1 end " + System.currentTimeMillis());
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    }
    //其他代码保持不变
    

    程序运行结果如下:

    A A1 begin 1469711921794
    B A1 begin 1469711921795
    C A1 begin 1469711921795
    A:3
    B:2
    B A1 end 1469711926799
    C A1 end 1469711926799
    A A1 end 1469711926799
    B A2 begin 1469711926799
    A A2 begin 1469711926800
    B A2 end 1469711926800
    A A2 end 1469711926800
    

    此时程序可以正常结束。


    onAdvance()方法
    public class MyService {
    	private Phaser phaser;
    	public MyService(Phaser phaser) {
    		super();
    		this.phaser = phaser;
    	}
    	
    	public void testMethod() {
    		try {
    			System.out.println("阶段1 Begin " + Thread.currentThread().getName() + System.currentTimeMillis());
    			if (Thread.currentThread().getName().equals("B")) {
    				Thread.sleep(5000);
    			}
    			phaser.arriveAndAwaitAdvance();
    			System.out.println("阶段1 End " + Thread.currentThread().getName() + " end phase value=" + phaser.getPhase() + "   " + System.currentTimeMillis());
    			/********/
    			System.out.println("阶段2 Begin " + Thread.currentThread().getName() + System.currentTimeMillis());
    			if (Thread.currentThread().getName().equals("B")) {
    				Thread.sleep(5000);
    			}
    			phaser.arriveAndAwaitAdvance();
    			System.out.println("阶段2 End " + Thread.currentThread().getName() + " end phase value=" + phaser.getPhase() + "   " + System.currentTimeMillis());
    			/********/
    			System.out.println("阶段3 Begin " + Thread.currentThread().getName() + System.currentTimeMillis());
    			if (Thread.currentThread().getName().equals("B")) {
    				Thread.sleep(5000);
    			}
    			phaser.arriveAndAwaitAdvance();
    			System.out.println("阶段3 End " + Thread.currentThread().getName() + " end phase value=" + phaser.getPhase() + "   " + System.currentTimeMillis());
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    }
    
    //省略ThreadA、ThreadB
    public class Main {
    	public static void main(String[] args) {
    		Phaser phaser = new Phaser(2){
    			@Override
    			protected boolean onAdvance(int phase, int registeredParties) {
    				System.out.println("onAdvance 被" + Thread.currentThread().getName() + "调用 " + System.currentTimeMillis() + " phase value=" + phase + " registeredParties=" + registeredParties);
    				return false;
    				//返回true 不等待,Phaser呈无效/销毁的状态
    				//返回false则Phaser继续工作
    			}	
    		};
    		MyService service = new MyService(phaser);
    		ThreadA a = new ThreadA(service);
    		a.setName("A");
    		a.start();
    		ThreadB b = new ThreadB(service);
    		b.setName("B");
    		b.start();
    	}
    }
    

    运行程序,控制台打印结果如下:

    阶段1 Begin A1470103011668
    阶段1 Begin B1470103011669
    onAdvance 被B调用 1470103016670 phase value=0 registeredParties=2
    阶段1 End B end phase value=1   1470103016670
    阶段1 End A end phase value=1   1470103016670
    阶段2 Begin A1470103016670
    阶段2 Begin B1470103016670
    onAdvance 被B调用 1470103021675 phase value=1 registeredParties=2
    阶段2 End B end phase value=2   1470103021675
    阶段2 End A end phase value=2   1470103021675
    阶段3 Begin A1470103021675
    阶段3 Begin B1470103021675
    onAdvance 被B调用 1470103026677 phase value=2 registeredParties=2
    阶段3 End B end phase value=3   1470103026677
    阶段3 End A end phase value=3   1470103026677
    

    onAdvance()在B线程到达屏障点时被调用。如果在onAdvance()方法中返回true,Phaser会被销毁。

    对main函数中的代码做如下修改:

    public class Main {
    	public static void main(String[] args) {
    		Phaser phaser = new Phaser(2){
    			@Override
    			protected boolean onAdvance(int phase, int registeredParties) {
    				System.out.println("onAdvance 被" + Thread.currentThread().getName() + "调用 " + System.currentTimeMillis() + " phase value=" + phase + " registeredParties=" + registeredParties);
    				return true;
    				//返回true 不等待,Phaser呈无效/销毁的状态
    				//返回false则Phaser继续工作
    			}	
    		};
    		MyService service = new MyService(phaser);
    		ThreadA a = new ThreadA(service);
    		a.setName("A");
    		a.start();
    		ThreadB b = new ThreadB(service);
    		b.setName("B");
    		b.start();
    	}
    }
    

    重新运行程序,控制台打印结果如下:

    阶段1 Begin A1470103416899
    阶段1 Begin B1470103416899
    onAdvance 被B调用 1470103421901 phase value=0 registeredParties=2
    阶段1 End B end phase value=-2147483647   1470103421901
    阶段1 End A end phase value=-2147483647   1470103421901
    阶段2 Begin B1470103421901
    阶段2 Begin A1470103421901
    阶段2 End A end phase value=-2147483647   1470103421901
    阶段3 Begin A1470103421901
    阶段3 End A end phase value=-2147483647   1470103421902
    阶段2 End B end phase value=-2147483647   1470103426905
    阶段3 Begin B1470103426905
    阶段3 End B end phase value=-2147483647   1470103431907
    

    arrive()方法

    arrive()方法的作用是使parties值加1,并且不在屏障处等待,直接向下面的代码继续运行,并且充值Phaser类的计数。

    public class Run {
    	public static void main(String[] args) {
    		Phaser phaser = new Phaser(2){
    			@Override
    			protected boolean onAdvance(int phase, int registeredParties) {
    				System.out.println("到达了未通过!phase=" + phase + " registeredParties=" + registeredParties);
    				return super.onAdvance(phase, registeredParties);
    			}
    		};
    		System.out.println("A1,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
    		phaser.arrive();
    		System.out.println("A1,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
    		System.out.println("A2,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
    		phaser.arrive();
    		System.out.println("A2,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
    		//---------
    		System.out.println("B1,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
    		phaser.arrive();
    		System.out.println("B1,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
    		System.out.println("B2,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
    		phaser.arrive();
    		System.out.println("B2,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
    		//---------
    		System.out.println("C1,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
    		phaser.arrive();
    		System.out.println("C1,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
    		System.out.println("C2,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
    		phaser.arrive();
    		System.out.println("C2,getPhase=" + phaser.getPhase() + " getRegisteredParties=" + phaser.getRegisteredParties() + " getArrivedParties=" + phaser.getArrivedParties());
    	}
    }
    

    运行程序,控制台打印结果如下:

    A1,getPhase=0 getRegisteredParties=2 getArrivedParties=0
    A1,getPhase=0 getRegisteredParties=2 getArrivedParties=1
    A2,getPhase=0 getRegisteredParties=2 getArrivedParties=1
    到达了未通过!phase=0 registeredParties=2
    A2,getPhase=1 getRegisteredParties=2 getArrivedParties=0
    B1,getPhase=1 getRegisteredParties=2 getArrivedParties=0
    B1,getPhase=1 getRegisteredParties=2 getArrivedParties=1
    B2,getPhase=1 getRegisteredParties=2 getArrivedParties=1
    到达了未通过!phase=1 registeredParties=2
    B2,getPhase=2 getRegisteredParties=2 getArrivedParties=0
    C1,getPhase=2 getRegisteredParties=2 getArrivedParties=0
    C1,getPhase=2 getRegisteredParties=2 getArrivedParties=1
    C2,getPhase=2 getRegisteredParties=2 getArrivedParties=1
    到达了未通过!phase=2 registeredParties=2
    C2,getPhase=3 getRegisteredParties=2 getArrivedParties=0
    

    方法arrive()的功能是使getArrivedParties()计数加1,不等待其他线程到达屏障。控制台多次出现getArrivedParties=0说明Phaser类经过屏障点后计数被重置。


    arriveAdvance(int phase)方法的作用是:如果传入参数phase值和当前getPhase()方法返回值一样,则在屏障处等待,否则继续向下面运行。

    public class ThreadA extends Thread {
    	private Phaser phaser;
    	public ThreadA(Phaser phaser) {
    		super();
    		this.phaser = phaser;
    	}
    	
    	@Override
    	public void run() {
    		System.out.println(Thread.currentThread().getName() + " A1 begin " + System.currentTimeMillis());
    		phaser.arriveAndAwaitAdvance();
    		System.out.println(Thread.currentThread().getName() + " A1 end " + System.currentTimeMillis());
    	}
    }
    
    public class ThreadB extends Thread {
    	private Phaser phaser;
    	public ThreadB(Phaser phaser) {
    		super();
    		this.phaser = phaser;
    	}
    	
    	@Override
    	public void run() {
    		System.out.println(Thread.currentThread().getName() + " A1 begin " + System.currentTimeMillis());
    		phaser.arriveAndAwaitAdvance();
    		System.out.println(Thread.currentThread().getName() + " A1 end " + System.currentTimeMillis());
    	}
    }
    
    public class ThreadC extends Thread {
    	private Phaser phaser;
    	public ThreadC(Phaser phaser) {
    		super();
    		this.phaser = phaser;
    	}
    	
    	@Override
    	public void run() {
    		try {
    			System.out.println(Thread.currentThread().getName() + " A1 begin " + System.currentTimeMillis());
    			Thread.sleep(3000);
    			phaser.awaitAdvance(0);//跨栏的栏数。不参与parties计数的操作,仅具有判断功能。
    			System.out.println(Thread.currentThread().getName() + " A1 end " + System.currentTimeMillis());
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    }
    
    public class ThreadD extends Thread {
    	private Phaser phaser;
    	public ThreadD(Phaser phaser) {
    		super();
    		this.phaser = phaser;
    	}
    	
    	@Override
    	public void run() {
    		try {
    			System.out.println(Thread.currentThread().getName() + " A1 begin " + System.currentTimeMillis());
    			Thread.sleep(5000);
    			phaser.arriveAndAwaitAdvance();
    			System.out.println(Thread.currentThread().getName() + " A1 end " + System.currentTimeMillis());
    		} catch (InterruptedException e) {
    			e.printStackTrace();
    		}
    	}
    }
    
    public class Main {
    	public static void main(String[] args) {
    		Phaser phaser = new Phaser(3);
    		ThreadA a = new ThreadA(phaser);
    		a.setName("A");
    		a.start();
    		ThreadB b = new ThreadB(phaser);
    		b.setName("B");
    		b.start();
    		ThreadC c = new ThreadC(phaser);
    		c.setName("C");
    		c.start();
    		ThreadD d = new ThreadD(phaser);
    		d.setName("D");
    		d.start();
    	}
    }
    

    程序运行结果如下:

    A A1 begin 1470226617412
    B A1 begin 1470226617412
    C A1 begin 1470226617413
    D A1 begin 1470226617414
    C A1 end 1470226622416
    B A1 end 1470226622416
    A A1 end 1470226622416
    D A1 end 1470226622416
    
  • 相关阅读:
    asp.net调用mysql 存储过程 带 out 返回值,返回刚插入数据库中的自增的ID,LAST_INSERT_ID() 的使用
    如何俘获一个 IT 男的心,让他成为男友然后变成老公?
    MySqlHelper.cs mysql数据库助手类
    mysql 按年度、季度、月度、周、日SQL统计查询,mysql 存储过程 中 in 和 FIND_IN_SET 传递多个参数的使用
    奇怪的母版页里面的 form 表单里面的 enctype="multipart/formdata" html控件上传 FileUpload控件上传 一次多图片上传
    asp.net 连接 Mysql 代码生成器(下载地址)
    Convert.ToInt32、(int)和int.Parse,int.TryParse四者之间的区别:
    在web项目中 使用 WebService 根据IP地址来源搜索实际物理地址,常用的WebServices
    vc6控制台程序利用SoapToolkit3.0调用WebService
    浅议C++/CLI的gcnew关键字
  • 原文地址:https://www.cnblogs.com/umgsai/p/5671644.html
Copyright © 2020-2023  润新知