Android 信号量Semaphore封装

Semaphore的介绍别的博客都有,原理方法什么的, 但是没有封装的,这个主要是讲如何封装的,想要去学习原理的话,去别的博客吧。

首先粘贴代码,工具封装类

/**
 * Created by EDZ on 2021/7/23.
 * Describe:Semaphore封装类
 */
public class Test implements Runnable {
    private static CountDownLatch latch = new CountDownLatch(1);
    //信号量,第一个为可用钥匙数量,第二个为是否公平模式,公平模式为按顺序执行,不公平模式自己抢
    //需要用volatile修饰,test本身需要成为全局工具,避免反复创建Semaphore,不然会失效
        private static volatile  Semaphore semaphore = new Semaphore(1, true);
        //用来执行的接口
    private static TestInterface testInterface;
    public void run() {
        try {
         //启动线程池调用
            latch.await();
            this.work();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
//执行信号量取钥匙操作
    private void work()  {
        try {
            //查询是否有空余的钥匙可以使用, 有返回true,没有返回false
            //第一个为申请钥匙数量,第二个为超时时间,第三个是超时单位
            //需要注意,返回true的时候,tryAcquire本身就会持有钥匙,不需要在调用acquire
        boolean b = semaphore.tryAcquire(1,5, TimeUnit.SECONDS);
        if (b==true){
            if (testInterface!=null){
                testInterface.setThread();
            }else {
                semaphore.release();
            }
        }else {
        //执行失败的处理,可以同样用接口回调, 我的处理方式是舍弃
        }
        } catch (InterruptedException e) {
            e.printStackTrace();
            LogUtil.e("子线程 失败:");
        }
    }

    
    //信号封锁执行完毕,释放钥匙
    public void setNum() {
        LogUtil.e("子线程结束:");
        semaphore.release();

    }

    //添加新的锁来尝试获取钥匙
    public void setTest(TestInterface test) {
        LogUtil.e("子线程添加:");
        testInterface = test;
        Thread t = new Thread(new Test());
        t.start();
        //保证所有线程同时运行
        latch.countDown();
    }

    //回传的接口,根据需求自己随便改
    public interface TestInterface {
        void setThread();
    }
}

这就是封装好了,为了避免工具类反复创建,造成信号锁重复申请创建,可以直接在

Application中初始化,作为全局使用, 如果需要多个不互相影响的锁,就多创建几个实例就可以
public class MyApp extends Application {
    public static Test test;
    public static Test getTest(){
        return test;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        test=new Test();
    }
}

接下来是在项目中使用

/**
 * Created by EDZ on 2021/7/16.
 * Describe:信号量调用类
 */
public class XinhaoliangActivity extends AppCompatActivity implements View.OnClickListener
         {
    Button bt_a, bt_b;

Test test;
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_xinhaoliang);
        //注册监听
        EventBus.getDefault().register(this);
        bt_a = findViewById(R.id.bt_a);
        bt_b = findViewById(R.id.bt_b);
        bt_a.setOnClickListener(this);
        bt_b.setOnClickListener(this);
         test=MyApp.getTest();
    }
    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.bt_a:

                test.setTest(new Test.TestInterface() {
                    @Override
                    public void setThread() {
                        //模拟延时操作的子线程,这里也是处理获取钥匙后的业务逻辑
                        ThreadUtils threadUtils = new ThreadUtils(XinhaoliangActivity.this);
                        threadUtils.start();
                    }
                });
                break;
            case R.id.bt_b:
                test.setTest(new Test.TestInterface() {
                    @Override
                    public void setThread() {
                        //简单的跳转,过去之后记得将信号释放
                   Intent intent=new Intent(XinhaoliangActivity.this,MainActivity.class);
                   startActivity(intent);
                    }
                });
                break;
        }
    }
    //接收订阅TestEvent事件的执行函数,当接收到发布者发布的TestEvent事件后会被调用
    @Subscribe(threadMode = ThreadMode.MAIN)
    public void onEventMainThread(MessageBean event) {
//        LogUtil.e("子线程结束:");
        test.setNum();
    }
}

布局

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">
<Button
    android:id="@+id/bt_a"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="A"
    />
    <Button
        android:id="@+id/bt_b"

        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="b"
        />

</LinearLayout>

跳转类

public class MainActivity extends AppCompatActivity {

    private File temp;
    Test test;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        test=MyApp.getTest();
        test.setNum();//释放信号量的钥匙
    }

}

子线程延时模拟类

public class ThreadUtils extends Thread implements XinInterface.Presenter {
    Context mContext;
    volatile int item = 0;
    public ThreadUtils(Context context ) {
        this.mContext = context;
    }
    @Override
    public void run() {
        super.run();

        while (true) {
            try {
                sleep(1000);

                    item++;
                    LogUtil.e("子线程:"  + "  " + item);
                    if (item ==10) {
                        EventBus.getDefault().post(
                                new MessageBean(0,"",""));
                        item=0;
                        return;
                    }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

eventbus传值类

public class MessageBean {
    private int code;
    private String message;
    private String data;

    public MessageBean(int code, String message, String data) {
        this.code = code;
        this.message = message;
        this.data = data;
    }

    public void setCode(int code) {
        this.code = code;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public void setData(String data) {
        this.data = data;
    }

    public int getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }

    public String getData() {
        return data;
    }

    @Override
    public String toString() {
        return "MessageBean{" +
                "code=" + code +
                ", message='" + message + '\'' +
                ", data='" + data + '\'' +
                '}';
    }
}

好了,整个信号量的封装就完成了,看不懂的,上面的全沾到项目里,让XinhaoliangActivity作为默认启动类就可以了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值