Android之Semaphore使用

Semaphore(信号量),是一种共享锁,多个线程同时访问一个资源时,通过它实现同一时刻的访问线程数量。位于java.util.concurrent.Semaphore,最常见的使用场景就是高并发下的限流。

举个例子:有10000辆车同时要涌入高速公路,但高速入口没有ETC只有2条人工发卡车道,所有人都必须要被收费亭许可(收费亭确认放行)后才能进入高速。高速公路是大家要共同使用的资源,收费亭就是Semaphore,2个发卡通道是Semaphore的同时允许车辆通过的许可证数量

使用代码示例:



public class TestCar {
​
    //收费站同时容纳的车辆2
    private  static  Semaphore semaphore=new Semaphore(2);
​
    public static void main(String[] args) {
​
        //模拟100辆车进入停车场
        for(int i=0; i<10000; i++){
​
            Thread thread=new Thread(new Runnable() {
                public void run() {
                    try {
                        System.out.println("===="+Thread.currentThread().getName()+"来到收费站");
                        if(semaphore.availablePermits()==0) {
                            System.out.println("工作人员正为其他车辆发卡,请耐心等待");
                        }
                        semaphore.acquire();//获取令牌尝试进入收费亭
                        System.out.println(Thread.currentThread().getName()+"成功进入收费亭");
                        //.....
                        //模拟车辆在收费亭停留时间
                        System.out.println(Thread.currentThread().getName()+"驶入高速公路");
                        semaphore.release();//释放令牌,腾出车位,处理下一台车
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }, i + "号车");
​
            thread.start();

        }
    }
}

其他用法:利用new Semaphore(0) 进行初始化控制,初始化完成后通过Semaphore.release释放锁,继续执行其他代码。以场景说明:外卖快递员收到推送过来的订单,进行订单信息梳理确认,开始派送订单到客户手上

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 收到订单
        String orderData = "你收到新的外卖订单,订单详情....";
        // 处理订单
        Postman.getInstance().onReceiveOrder(orderData);
    }
}


/**
 * 注意:实现了Runnable接口
 */
public class Postman implements Runnable {
    private static Postman mInstance;
    private Semaphore semaphore = new Semaphore(0);

    // 初始化
    public static Postman getInstance() {
        if (null == mInstance) {
            synchronized (Postman.class) {
                if (null == mInstance) {
                    mInstance = new Postman();
                }
            }
        }
        return mInstance;
    }

    public void onReceiveOrder(String data) {
        System.out.println("处理订单数据,确认收货人姓名、地址等,代码略……");
        // 这句代码,会释放锁进入run()方法,触发开始派送流程
        semaphore.release();
    }

    // 开启一个后台线程,执行派送订单操作
    public Postman() {
        new Thread(this).start();
    }

    @Override
    public void run() {
        // 循环检查订单,如果有订单进行派送
        while (true) {
            if (semaphore.tryAcquire()) { // 因为许可证数量是0,这里会一直阻塞,直到释放锁(semaphore.release) 才会执行下面代码
                System.out.println("收到订单,开始派送,代码自行扩展....");
            } else {
                try {
                    Thread.sleep(1000);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}

从上面代码可以看出:在订单处理没有完成之前,semaphore会一直等待release通知,阻塞派单流程的代码,知道release释放锁后,才会往下执行。

你可能感兴趣的:(JAVA,性能效率,java,开发语言,后端)