Java线程同步器

1.CyclicBarrier(屏障)

   CyclicBarrier类是通过设置屏障点来管理同步的,当所有参与的线程都到达指定屏障的时候,那么参与的所有线程就会全部    积蓄运行,具体测试代码如下:

 

public class CyclicBarrierTest {
	// 定义一个循环屏障
	private CyclicBarrier cyclicBarrier;

	// 构造函数
	//count为参与执行的线程数
	//rn为所有线程到达屏障后需要做的行为
	public CyclicBarrierTest(int count, Runnable rn) {
		this.cyclicBarrier = new CyclicBarrier(count, rn);
	}

	public void sayHello(String name, int time) {
		System.out.println("开始执行:" + name);
		try {
			Thread.sleep(time);
			this.cyclicBarrier.await();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (BrokenBarrierException e) {
			e.printStackTrace();
		}
		System.out.println("结束执行:" + name);
	}

	public static void main(String[] args) {
		final CyclicBarrierTest cbt = new CyclicBarrierTest(3, new Runnable() {

			@Override
			public void run() {
				System.out.println("执行数量的线程完成后执行");
			}

		});
		// 创建三个测试线程
		Thread t1 = new Thread(new Runnable() {

			@Override
			public void run() {
				cbt.sayHello("T1", 500);
			}

		});

		Thread t2 = new Thread(new Runnable() {

			@Override
			public void run() {
				cbt.sayHello("T2", 1000);
			}

		});

		Thread t3 = new Thread(new Runnable() {

			@Override
			public void run() {
				cbt.sayHello("T3", 2000);
			}

		});
                //启动三个线程
		t1.start();
		t2.start();
		t3.start();
	}
}

 

 

       上述代码的运行结果,应该是:

           开始执行:T1

            开始执行:T2

            开始执行:T3

            执行数量的线程完成后执行

            结束执行:T1

            结束执行:T2

            结束执行:T3

2.CountDownLatch(计数)

    CountDownLatch类是通过线程计数来实现同步的,也就是有一个计数器,在计数器未到0之前所有相关线程在指定位置都需要阻   塞,直到计数器为0的时候,所有相关线程停止阻塞,继续向下执行。需要注意的是,该同步器不能被复用,并且可以由外部事件触发。

 

public class CountDownLatchTest {
	
	private CountDownLatch countDownLatch = null;
	//构造函数,创建倒计时同步器
	//count为倒计时数
	public CountDownLatchTest(int count){
		this.countDownLatch = new CountDownLatch(count);
	}
	
	//递减计数器
	public void countDown(){
		this.countDownLatch.countDown();
		System.out.println("count:" + this.countDownLatch.getCount());
	}
	
	public void sayHello(String name, int time) {
		System.out.println("开始执行:" + name);
		try {
			Thread.sleep(time);
			this.countDownLatch.await();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("结束执行:" + name);
	}
	
	public static void main(String[] args) throws InterruptedException {
		final CountDownLatchTest cdl = new CountDownLatchTest(3);
		// 创建三个测试线程
		Thread t1 = new Thread(new Runnable() {

			@Override
			public void run() {
				cdl.sayHello("T1", 50);
			}

		});

		Thread t2 = new Thread(new Runnable() {

			@Override
			public void run() {
				cdl.sayHello("T2", 50);
			}

		});

		Thread t3 = new Thread(new Runnable() {

			@Override
			public void run() {
				cdl.sayHello("T3", 50);
			}

		});
		//启动测试线程
		t1.start();
		t2.start();
		t3.start();
		
		Thread.sleep(2000);
		//逐步递减
		cdl.countDown();
		Thread.sleep(1000);
		cdl.countDown();
		Thread.sleep(1000);
		cdl.countDown();
		Thread.sleep(1000);
	}
}

      上述代码由于线程运行的不确定性,每次的运行结果都不一样,但原则不变,例如:

 

          开始执行:T1

           开始执行:T2

           开始执行:T3

           count:2

           count:1

           count:0

           结束执行:T2

           结束执行:T3

           结束执行:T1

 

3.Exchanger(交换)

    Exchanger类用于不同线程间交换数据,并且交换过程是线程安全的,通过设置一个同步点来实现,具体代码如下:

 

public class ExchangerTest {
	private Exchanger<String> exchanger;
	
	public ExchangerTest(){
		this.exchanger = new Exchanger<String>();
	}
	
	public void method1(String name){
		System.out.println("执行Mehtod1");
		//Thread.sleep(1000);\
		String ss = name + "发送数据:123123" ;
		try {
			ss = this.exchanger.exchange(ss);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("结束Mehtod1");
	}
	
	public void method2(String name){
		System.out.println("执行Mehtod2");
		String ss = "123";
		try {
			ss = this.exchanger.exchange(ss);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		System.out.println("Mehotd2收到:" + ss);
		System.out.println("结束Mehtod2");
	}
	
	public static void main(String[] args) {
		final ExchangerTest et = new ExchangerTest();
		// 创建三个测试线程
		Thread t1 = new Thread(new Runnable() {

			@Override
			public void run() {
				et.method1("T1");
			}

		});

		Thread t2 = new Thread(new Runnable() {

			@Override
			public void run() {
				et.method2("T2");
			}

		});
		//启动测试线程
		t2.start();
		t1.start();
	}
}

 

 

        上述代码的运行结果,应该是:

          执行Mehtod2

           执行Mehtod1

           结束Mehtod1

           Mehotd2收到:T1发送数据:123123

           结束Mehtod2

 

4.SynchronousQueue(同步队列)

    该同步器是阻塞队列的一种,虽然称之为队列,但是该“队列”没有长度。使用该队列的规则是:没有存不允许取,没有取不允许存。该队列的方法很多,但一般使用较多的是put和take方法,因为这两个方法实现了阻塞方式的存取,代码如下:

 

public class SynchronousQueueTest {
	private SynchronousQueue<String> synchronousQueue;
	
	public SynchronousQueueTest(){
		//构造函数内的参数表示是否采取公平策略
		//即优先照顾等待时间比较长的线程
		//使用公平策略会影响性能
		this.synchronousQueue = new SynchronousQueue<String>(false);
	}
	
	public void put(String data){
		try {
			System.out.println("等待放入:" + data);
			this.synchronousQueue.put(data);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	
	public String take(){
		String data = null;
		try {
			data = this.synchronousQueue.take();
			System.out.println("提取了:" + data);
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		return data;
	}
	
	
	public static void main(String[] args) {
		final SynchronousQueueTest sqt = new SynchronousQueueTest();
		// 创建三个测试线程
		Thread t1 = new Thread(new Runnable() {

			@Override
			public void run() {
				sqt.put("111111");
				try {
					Thread.sleep(4000);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				sqt.put("222222");
			}

		});

		Thread t2 = new Thread(new Runnable() {

			@Override
			public void run() {
				sqt.take();
				sqt.take();
				
			}

		});
		//启动测试线程
		t1.start();
		t2.start();
	}
}

     上述代码的运行结果,应该是:

 

          等待放入:111111

           提取了:111111

           等待放入:222222

           提取了:222222

5.Semaphore(信号量)

   Semaphore类通过类似许可证的方式对同步进行管理,简单的来说,许可证的数目是一定的,想要访问,必须要获得许可证,若许可证已经用完,那么必须等待其他占用许可证的线程归还许可证后,方可得到许可从而继续执行。具体代码如下:

 

public class SemaphoreTest {
	private Semaphore semaphore;
	
	//构造函数用于创建一个信号量同步器
	//count为许可个数
	//fair表示是否采用公平策略
	public SemaphoreTest(int count,boolean fair){
		this.semaphore = new Semaphore(count,fair);
	}
	
	public void sayHello(String name){
		try {
			this.semaphore.acquire();
			System.out.println(name + "得到许可");
			Thread.sleep(5000);
			this.semaphore.release();
			System.out.println(name + "释放许可");
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
	}
	
	public static void main(String[] args) {
		final SemaphoreTest st = new SemaphoreTest(3,false);
		// 创建测试线程
		Thread t1 = new Thread(new Runnable() {

			@Override
			public void run() {
				st.sayHello("T1");
			}

		});

		Thread t2 = new Thread(new Runnable() {

			@Override
			public void run() {
				st.sayHello("T2");
			}

		});

		Thread t3 = new Thread(new Runnable() {

			@Override
			public void run() {
				st.sayHello("T3");
			}

		});
		
		Thread t4 = new Thread(new Runnable() {

			@Override
			public void run() {
				st.sayHello("T4");
			}

		});
		
		Thread t5 = new Thread(new Runnable() {

			@Override
			public void run() {
				st.sayHello("T5");
			}

		});
		t1.start();
		t2.start();
		t3.start();
		t4.start();
		t5.start();
	}
}

    上述代码由于线程运行的不确定性,每次的运行结果都不一样,但原则不变,例如:

 

          T1得到许可

           T2得到许可

           T4得到许可

           T2释放许可

           T4释放许可

           T3得到许可

           T1释放许可

           T5得到许可

           T3释放许可

           T5释放许可

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值