`

Java 并发常用工具类

 
阅读更多
很多情况下 程序的主线程在做一项工作之前需要一系列的准备工作,只有这些准备工作都完成,主线程才能继续它的工作,
CountDownLatch允许一个或多个线程等待另外N个线程完成某个操作之后才能执行这个类似Thread里的join()的功能。当某一个或多个线程start()以后,
用join()去等待。必须对应的线程执行完毕,join()后续的代码才能继续执行下去,CountDownLatch提供了join()的类似功能,并且能提供的更多! 
CountDownLatch提供了int参数(计数器)的构造方法,输入N就代表等待N个点完成。当我们调用countDown()方法时N就减1,直到N为0,await()后续代码才能继续执行
import java.util.concurrent.CountDownLatch;

public class Test {
     public static void main(String[] args) {   
         final CountDownLatch latch = new CountDownLatch(2);
          
         new Thread(){
             public void run() {
                 try {
                     System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");
                    Thread.sleep(3000);
                    System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");
                    latch.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
             };
         }.start();
          
         new Thread(){
             public void run() {
                 try {
                     System.out.println("子线程"+Thread.currentThread().getName()+"正在执行");
                     Thread.sleep(3000);
                     System.out.println("子线程"+Thread.currentThread().getName()+"执行完毕");
                     latch.countDown();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
             };
         }.start();
          
         try {
             System.out.println("等待2个子线程执行完毕...");
            latch.await();
            System.out.println("2个子线程已经执行完毕");
            System.out.println("继续执行主线程");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
     }
}

-----------------------------------------------------------------------------------------------------------------------------------------
CyclicBarrier

允许两个或者多个线程在某个集合点同步。当一个线程到达集合点时,它将调用await()方法等待其它的线程。线程调用await()方法后,
CyclicBarrier将阻塞这个线程并将它置入休眠状态等待其它线程的到来。等最后一个线程调用await()方法时,CyclicBarrier将唤醒所有等待的线程然后这些线程将继续执行。
CyclicBarrier可以传入另一个Runnable对象作为初始化参数。当所有的线程都到达集合点后,CyclicBarrier类将Runnable对象作为线程执行.

示例1.
class TaskDemo implements Runnable{
	 private static Random rnd = new Random();
    private String id;
    TaskDemo(String id){
        this.id = id;
    }
    @Override
    public void run(){
        try {
            Thread.sleep(rnd.nextInt(1000));
            System.out.println("Thread " + id + " will wait");
            TestCyclicBarrier.cb.await();
            System.out.println("-------Thread " + id + " is over");
        } catch (InterruptedException e) {
        } catch (BrokenBarrierException e) {
        }
    }
}
public class TestCyclicBarrier {
    public static CyclicBarrier cb = new CyclicBarrier(4);
    public static void main(String[] args){
        ExecutorService es = Executors.newCachedThreadPool();
        es.submit(new TaskDemo("a"));
        es.submit(new TaskDemo("b"));
        es.submit(new TaskDemo("c"));
        es.submit(new TaskDemo("d"));
        es.shutdown();
    }
}

//输出结果如下:
Thread b will wait
Thread c will wait
Thread d will wait
Thread a will wait
-------Thread b is over
-------Thread c is over
-------Thread a is over
-------Thread d is over

CyclicBarrier还提供一个更高级的构造函数CyclicBarrier(int parties, Runnable barrierAction),用于在线程到达屏障时,先执行barrierAction再释放其他线程锁
,方便处理更复杂的业务场景。
代码如下:

public class CyclicBarrierTest2 {
	//在线程到达屏障时,先执行A任务,待A任务返回后再释放其他线程的锁
	static CyclicBarrier c = new CyclicBarrier(2, new A());
	public static void main(String[] args) {
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					c.await();
				} catch (Exception e) {
				}
				System.out.println(1);
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					c.await();
				} catch (Exception e) {
				}
				System.out.println(2);
			}
		}).start();
	}
	static class A implements Runnable {
		@Override
		public void run() {
			try {
				Thread.sleep(10000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(3);
		}
	}
}
//输出结果如下:
3
1
2
-----------------------------------------------------------------------------------------------------------------------------------------
Semaphore

Semaphore可以用于做流量控制,特别公用资源有限的应用场景,比如数据库连接。
假如有一个需求,要读取几万个文件的数据,因为都是IO密集型任务,我们可以启动几十个线程并发的读取,
但是如果读到内存后,还需要存储到数据库中,而数据库的连接数只有10个,
这时我们必须控制只有十个线程同时获取数据库连接保存数据,否则会报错无法获取数据库连接。
这个时候,我们就可以使用Semaphore来做流控.

Semaphore的用法也很简单,首先线程使用Semaphore的acquire()获取一个许可证,使用完之后调用release()归还许可证。
class SemaphoreTest {
	private static int threadCount = 100;
	static Semaphore semaphore = new Semaphore(10);
	static ExecutorService service = Executors.newFixedThreadPool(threadCount);// 创建大小为100的线程池

	public static void main(String[] argus) {
		for (int i = 0; i < threadCount; i++) {
			final int c = i;
			service.execute(new Runnable() {
				@Override
				public void run() {
					try {
						semaphore.acquire();// 获取许可(绿灯)
						System.out.println("执行一些频繁的资源逻辑操作" + c);
						Thread.sleep(1000);
						semaphore.release();// 释放一个许可
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
				}
			});
		}
		service.shutdown();
	}
}
-----------------------------------------------------------------------------------------------------------------------------------------


Exchanger
Exchanger也很好理解,直译交换者,是用于2个线程之间交互数据的工具类,它提供了一个同步点,
其中一个线程先执行了exchange方法,会一直等待第二个线程执行到exchange方法,直到都达到了执行点,两个线程才交互数据

class TestExchanger {
    static Exchanger<Double> exchanger = new Exchanger<Double>();//定义交换者
    static ExecutorService service = Executors.newFixedThreadPool(2);//2个大小的线程池
    public static void main(String[] argus) {
        service.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    //例如录入银行流水计算一个总额 操作人A
                    Double a = new Double(100);
                    double exchangeB = exchanger.exchange(a);
                    System.out.println("A自己的数据为:"+a+" 交换得到了" + exchangeB);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        service.execute(new Runnable() {
            @Override
            public void run() {
                try {
                    //例如录入银行流水计算一个总额 操作人B
                    Double b = new Double(101);
                    double exchangeB = exchanger.exchange(b);
                    System.out.println("B自己的数据为:"+b+" 交换得到了:" + exchangeB);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        });
        service.shutdown();
    }
}
//输出
A自己的数据为:100.0 交换得到了101.0
B自己的数据为:101.0 交换得到了:100.0

 

分享到:
评论

相关推荐

    java并发编程实战中文加英文版加源码

    书籍是什么,是希望,是神圣的,你们这些译者简直就是在犯罪 ,不过要是英文功底不好,还是建议买本看吧,谁让你英文水平不如他们呢 《JAVA并发编程实践》随着多核处理器的普及,使用并发成为构建高性能应用程序的...

    java并发编程实践高清中文版+源码

    《JAVA并发编程实践》随着多核处理器的普及,使用并发成为构建高性能应用程序的关键。Java 5以及6在开发并发程序中取得了显著的进步,提高了Java虚拟机的性能以及并发类的可伸缩性,并加入了丰富的新并发构建块。在...

    JAVA并发编程实践

    《JAVA并发编程实践》随着多核处理器的普及,使用并发成为构建高性能应用程序的关键。Java 5以及6在开发并发程序中取得了显著的进步,提高了Java虚拟机的性能以及并发类的可伸缩性,并加入了丰富的新并发构建块。在...

    JAVA并发编程实践 .pdf

    如何提高单线程子系统的响应性,如何确保并发程序执行预期任务,如何提高并发代码的性能和可伸缩性等内容,最后介绍了一些高级主题,如显式锁、原子变量、非阻塞算法以及如何开发自定义的同步工具类。 《Java并发编程...

    《Java并发编程的艺术》

    《Java并发编程的艺术》内容涵盖Java并发编程机制的底层实现原理、Java内存模型、Java并发编程基础、Java中的锁、并发容器和框架、原子类、并发工具类、线程池、Executor框架等主题,每个主题都做了深入的讲解,同时...

    Java并发编程实战

    5.5 同步工具类 5.5.1 闭锁 5.5.2 FutureTask 5.5.3 信号量 5.5.4 栅栏 5.6 构建高效且可伸缩的结果缓存 第二部分 结构化并发应用程序 第6章 任务执行 6.1 在线程中执行任务 6.1.1 串行地执行任务 6.1.2 ...

    Java并发编程实战.rar

    《Java并发编程实战》是一本完美的Java并发参考手册。书中从并发性和线程安全性的基本概念出发,介绍了如何使用类库提供的基本并发构建块,用于避免并发危险、构造线程安全的类及验证线程安全的规则,如何将小的线程...

    JAVA并发编程实践高清中文带书签

    《JAVA并发编程实践》随着多核处理器的普及,使用并发成为构建高性能应用程序的关键。Java 5以及6在开发并发程序中取得了显著的进步,提高了Java虚拟机的性能以及并发类的可伸缩性,并加入了丰富的新并发构建块。在...

    JAVA并发编程实践.pdf

    《JAVA并发编程实践》随着多核处理器的普及,使用并发成为构建高性能应用程序的关键。Java 5以及6在开发并发程序中取得了显著的进步,提高了Java虚拟机的性能以及并发类的可伸缩性,并加入了丰富的新并发构建块。在...

    JAVA并发编程实践(英文版)

    《JAVA并发编程实践》随着多核处理器的普及,使用并发成为构建高性能应用程序的关键。Java 5以及6在开发并发程序中取得了显著的进步,提高了Java虚拟机的性能以及并发类的可伸缩性,并加入了丰富的新并发构建块。在...

    JAVA并发编程实践 带书签

    本书深入浅出地介绍了Java线程和并发,是一本完美的Java并发参考手册。书中从并发性和线程安全性的基本概念出发,介绍了如何使用类库提供的基本并发构建块,用于避免并发危险、构造线程安全的类及验证线程安全的规则...

    Java并发编程实战(华章专业开发者书库).mobi

    本书深入浅出地介绍了Java线程和并发,是一本完美的Java并发参考手册。书中从并发性和线程安全性的基本概念出发,介绍了如何使用类库提供的基本并发构建块,用于避免并发危险、构造线程安全的类及验证线程安全的规则...

    java并发编程实战相关书籍

    本书深入浅出地介绍了Java线程和并发,是一本完美的Java并发参考手册。书中从并发性和线程安全性的基本概念出发,介绍了如何使用类库提供的基本并发构建块,用于避免并发危险、构造线程安全的类及验证线程安全的规则...

    Java并发编程的艺术

    《Java并发编程的艺术》内容涵盖Java并发编程机制的底层实现原理、Java内存模型、Java并发编程基础、Java中的锁、并发容器和框架、原子类、并发工具类、线程池、Executor框架等主题,每个主题都做了深入的讲解,同时...

    精通Java并发编程(第2版)【试读】

    然后介绍了Thread类和Runnable接口,它们是Java并发API的重要组成部分。接着讨论了如何利用Java并发API的各种元素(从基本技巧到高级技巧),以及如何在强大的真实并发应用程序中实现它们。最后详细介绍了测试并发...

    Java 并发编程实战(中文+高清版).zip

    本书深入浅出地介绍了Java线程和并发,是一本完美的Java并发参考手册。书中从并发性和线程安全性的基本概念出发,介绍了如何使用类库提供的基本并发构建块,用于避免并发危险、构造线程安全的类及验证线程安全的规则...

    Java并发编程实战.pdf

    本书深入浅出地介绍了Java线程和并发,是一本完美的Java并发参考手册。书中从并发性和线程安全性的基本概念出发,介绍了如何使用类库提供的基本并发构建块,用于避免并发危险、构造线程安全的类及验证线程安全的规则...

    龙果java并发编程完整视频

    第37节并发工具类CountDownLatch详解00:22:04分钟 | 第38节并发工具类CyclicBarrier 详解00:11:52分钟 | 第39节并发工具类Semaphore详解00:17:27分钟 | 第40节并发工具类Exchanger详解00:13:47分钟 | 第41节...

Global site tag (gtag.js) - Google Analytics