Java高并发编程:同步工具类

本文深入探讨了Java中的同步工具,包括Semaphore、CyclicBarrier、CountDownLatch、Exchanger以及各种同步集合类,如ArrayBlockingQueue和ConcurrentHashMap等。通过实例展示了这些工具如何在多线程环境中实现资源控制、线程间通信和数据交换,帮助开发者更好地理解和应用并发编程技术。
摘要由CSDN通过智能技术生成

内容摘要

这里主要介绍了java5中线程锁技术以外的其他同步工具,首先介绍Semaphore:一个计数信号量。用于控制同时访问资源的线程个数,CyclicBarrier同步辅助类:从字面意思看是路障,这里用于线程之间的相互等待,到达某点后,继续向下执行。CountDownLatch同步辅助类:在完成一组正在其他线程中执行的操作之前,它允许一个或多个线程一直等待。犹如倒计时计数器,然后是Exchanger:实现两个对象之间数据交换,可阻塞队列:ArrayBlockingQueue,通过阻塞队列间的通信来演示其作用,最后介绍了几个同步集合。

1. Semaphore实现信号灯

Semaphore可以维护当前访问自身的线程个数,并提供了同步机制,使用Semaphore可以控制同时访问资源的线程个数,例如,实现一个文件允许的并发访问数。Semaphore 只对可用许可的号码进行计数,并采取相应的行动。

Semaphore实现的功能就像:银行办理业务,一共有5个窗口,但一共有10个客户,一次性最多有5个客户可以进行办理,其他的人必须等候,当5个客户中的任何一个离开后,在等待的客户中有一个人可以进行业务办理。

Semaphore提供了两种规则:

  • 一种是公平的:获得资源的先后,按照排队的先后。在构造函数中设置true实现
  • 一种是野蛮的:谁有本事抢到资源,谁就可以获得资源的使用权。

与传统的互斥锁的异同:

单个信号量的Semaphore对象可以实现互斥锁的功能,并且可以是由一个线程获得了“锁“,再由另外一个线程释放”锁“,这可以应用于死锁恢复的一些场合。

应用场景:共享资源的争夺,例如游戏中选手进入房间的情况。

import java.util.concurrent.ExecutorService;  
import java.util.concurrent.Executors;  
import java.util.concurrent.Semaphore;  

public class SemaphoreTest {
     
    public static void main(String[] args) {  

  //创建一个可根据需要创建新线程的线程池  
  ExecutorService service = Executors.newCachedThreadPool();  
        final  Semaphore sp = new Semaphore(3);  

  //创建10个线程  
  for(int i=0;i<10;i++){  
            Runnable runnable = new Runnable(){  
                    public void run(){  
                    try {  
                        sp.acquire();   //获取灯,即许可权  
                    } catch (InterruptedException e1) {  
                        e1.printStackTrace();  
                    }  
                    System.out.println("线程" + Thread.currentThread().getName() +   
                            "进入,当前已有" + (3-sp.availablePermits()) + "个并发");  
                    try {  
                        Thread.sleep((long)(Math.random()*10000));  
                    } catch (InterruptedException e) {  
                        e.printStackTrace();  
                    }  
                    System.out.println("线程" + Thread.currentThread().getName() +   
                            "即将离开");                      
                    sp.release();   // 释放一个许可,将其返回给信号量  

                    //下面代码有时候执行不准确,因为其没有和上面的代码合成原子单元  
                    System.out.println("线程" + Thread.currentThread().getName() +   
                            "已离开,当前已有" + (3-sp.availablePermits()) + "个并发");                      
                }  
            };  
            service.execute(runnable);            
        }  
    }  
}  

输出结果

线程pool-1-thread-3进入,当前已有3个并发
线程pool-1-thread-2进入,当前已有3个并发
线程pool-1-thread-1进入,当前已有3个并发
线程pool-1-thread-2即将离开
线程pool-1-thread-2已离开,当前已有2个并发
线程pool-1-thread-5进入,当前已有3个并发
线程pool-1-thread-1即将离开
线程pool-1-thread-1已离开,当前已有2个并发
线程pool-1-thread-4进入,当前已有3个并发
线程pool-1-thread-4即将离开
线程pool-1-thread-4已离开,当前已有2个并发
线程pool-1-thread-8进入,当前已有3个并发
线程pool-1-thread-3即将离开
线程pool-1-thread-7进入,当前已有3个并发
线程pool-1-thread-3已离开,当前已有3个并发
线程pool-1-thread-8即将离开
线程pool-1-thread-8已离开,当前已有2个并发
线程pool-1-thread-9进入,当前已有3个并发
线程pool-1-thread-7即将离开
线程pool-1-thread-7已离开,当前已有2个并发
线程pool-1-thread-6进入,当前已有3个并发
线程pool-1-thread-9即将离开
线程pool-1-thread-9已离开,当前已有2个并发
线程pool-1-thread-10进入,当前已有3个并发
线程pool-1-thread-5即将离开
线程pool-1-thread-5已离开,当前已有2个并发
线程pool-1-thread-6即将离开
线程pool-1-thread-6已离开,当前已有1个并发
线程pool-1-thread-10即将离开
线程pool-1-thread-10已离开,当前已有0个并发

控制一个方法的并发量,比如同时只能有3个线程进来

public class ThreadPoolTest {
   
    //信号量
    private static Semaphore semaphore = new Semaphore(3);//允许个数,相当于放了3把锁

    public static void main(String[] args) {

        for(int i=0;i<10;i++){

            new Thread(new Runnable() {

                @Override
                public void run() {
                    try {
                        method();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }

                }
            }).start();
        }

    }


    //同时最多只允许3个线程过来
    public static void method() throws InterruptedException{
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值