IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> Android 信号量Semaphore封装 -> 正文阅读

[移动开发]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作为默认启动类就可以了

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-07-24 11:36:36  更:2021-07-24 11:37:49 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/2 6:50:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码