`

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 并发工具类提供了多种解决方案来协调线程之间的并发执行,每种工具类都有其特点和应用场景,选择合适的工具类可以提高程序的效率和可读性。

    Java并发工具包

    包括 TimeUnit、ThreadLocalRandom 和 Phaser 等,这些工具类提供了在并发编程中常用的实用功能,如时间单位转换、随机数生成和同步阶段控制。 总结来说,Java并发工具包提供了丰富的工具和机制,帮助开发者构建...

    Java常用工具类大全,工作5年精心整理.zip

    "Java常用工具类大全,工作5年精心整理.zip"这个压缩包文件很可能包含了一位有经验的Java开发者在五年工作中积累的各种实用工具类,这些工具类能够极大地提高开发效率,简化代码编写。以下是对可能包含的知识点进行...

    Java 并发编程实战.pdf

    综合来看,该书不仅适合于对Java并发编程感兴趣的初学者,同样也适合有经验的开发者,作为一本参考资料和实践指南,读者可以通过它来加深对Java并发特性的理解和应用。书中丰富的案例分析和代码示例将有助于读者更...

    java常用工具类集合(也有转自他人的)

    "java常用工具类集合"是一个综合性的资源,它包含了从不同来源收集的实用工具类,旨在帮助开发者提高效率,减少代码重复。下面,我们将深入探讨这个主题,分析其中可能包含的知识点。 首先,`opslabJutil-master....

    java常用工具类

    5. **并发工具类**:`java.util.concurrent`包提供了高级并发工具,如ExecutorService、Semaphore、CountDownLatch、CyclicBarrier等,帮助开发者更有效地管理多线程程序。 6. **字符串处理**:`String`类是Java中...

    java工具类集合

    Java工具类集合是Java开发中不可或缺的一部分,它们提供了一系列便捷的方法,帮助开发者高效地处理各种常见任务。在Java中,工具类通常被组织在各种包下,如`java.util`、`java.lang`、`java.io`等。下面将详细介绍...

    java常用工具类封装

    在Java编程中,工具类(Util Classes)是包含各种实用...通过封装这些常用工具类,开发人员可以快速构建功能丰富的应用,提高代码质量,并降低维护成本。了解并熟练运用这些工具和库,对于提升Java开发效率至关重要。

    java并发编程实战源码,java并发编程实战pdf,Java

    《Java并发编程实战》是Java并发编程领域的一本经典著作,它深入浅出地介绍了如何在Java平台上进行高效的多线程编程。这本书的源码提供了丰富的示例,可以帮助读者更好地理解书中的理论知识并将其应用到实际项目中。...

    Java常用工具类

    Java常用工具类是Java开发中不可或缺的一部分,它们提供了一系列便捷的方法,帮助开发者高效地处理各种常见任务。在Java中,最著名的工具类库是`java.util`包,它包含了大量实用类,如集合、日期时间、数学计算、...

    java 常用工具类

    以上就是Java工具类中的核心知识点,它们在日常开发中有着广泛的应用。SuperUtility可能是一个自定义的工具类库,扩展了Java内置工具类的功能,或者提供了特定场景下的便捷方法。了解和熟练使用这些工具类,能够显著...

    牛逼的java常用工具类

    在这个名为"牛逼的java常用工具类"的压缩包中,我们可以期待找到一些由经验丰富的开发者精心设计和优化的工具类,这些工具类能极大地提高开发效率,减少代码量,使程序更加健壮。下面,我们将详细探讨一些可能包含在...

    28个java常用的工具类

    18. **ExecutorService和Future类**:Java并发库的一部分,用于管理线程池和异步任务。 19. **Properties类**:处理配置文件,存储和加载键值对。 20. **ClassLoader类**:用于加载类和资源,是Java动态加载机制的...

    Java常用工具类集合

    在Java编程语言中,工具类集合是一系列实用的类,它们提供了各种通用功能,帮助开发者更高效地编写代码。这些工具类通常包含在Java的`java.util`以及其他相关的包中,如`java.text`,`javax.imageio`,`javax.xml`等...

    JAVA开发常用工具类

    下面我们将深入探讨一些Java开发中常用的工具类,并了解它们在实际项目中的应用。 1. **`java.util.ArrayList` 和 `java.util.LinkedList`**: 这两个类都是`java.util.List`接口的实现,提供了动态数组和链表数据...

    java并发编程艺术

    此外,书中可能还会涉及其他并发编程相关的高级话题,比如原子变量(`AtomicInteger`, `AtomicReference`等)、并发工具类(如`CountDownLatch`, `CyclicBarrier`, `Semaphore`)以及Fork/Join框架。这些工具可以...

Global site tag (gtag.js) - Google Analytics