关于Java的Semaphore以及Android的Looper使用

Android的Looper使用-关于Android异步消息处理机制

最近在Android项目中看到这个关键词,一时间无从下手,这里先卖个关子:

        new Thread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(MainActivity.this, "弹个Toast", Toast.LENGTH_SHORT).show();
            }
        }).start();

直接在子线程弹个Toast的时候会出现崩溃,日志如下:
这里写图片描述



但是加上Looper又可以正常弹出Toast:

        new Thread(new Runnable() {
            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(MainActivity.this, "弹个Toast", Toast.LENGTH_SHORT).show();
                Looper.loop();
            }
        }).start();

关于Looper的作用看这篇文章:Android异步消息处理机制完全解析,带你从源码的角度彻底理解 - 郭霖的专栏 - CSDN博客 –这篇也可作为Handler源码的简单分析


运用Semaphore 来保证合理的使用资源

public final class RunInMain {
    /**
     * 在主线程运行runnable
     * @param waitUntilDone  直到等待完成
     * @param job             runnable接口
     */
    public static void dispatch(final boolean waitUntilDone, final Runnable job) {
        //主线程的标志
        boolean alreadyInMain = Thread.currentThread() == Looper.getMainLooper().getThread();
        if (alreadyInMain) {
            //如果是在主线程的话,直接运行
            job.run();
        } else {
            //如果不是在主线程的话,那么需要用到handler异步处理消息机制
            //这个Semaphore被称为信息量,http://www.jianshu.com/p/0090341c6b80(我暂时还没有看懂)
            final Semaphore semaphore = new Semaphore(0);
            new Handler(Looper.getMainLooper()).post(new Runnable() {//在主线程创建handlder
                @Override
                public void run() {
                    job.run();//主线程运行

                    if (waitUntilDone) {
                        semaphore.release();//使得信息量容许的线程数加1
                    }
                }
            });

            if (!waitUntilDone)
                return;

            try {
                semaphore.acquire();//使得信息量容许的线程数减1
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    public static void dispatch(Runnable job) {
        dispatch(false, job);
    }
}

当我看到这个Semaphore 的时候,我是一脸懵逼的,通过查看
Java的Semaphore使用总结 - CSDN博客 -这一篇建议运行一下他的代码理解以及
深入浅出java Semaphore - 简书 -这一篇建议看看源码
NO.54 并发限流: 信号量Semaphore

然后运用:

        new Thread(new Runnable() {
            @Override
            public void run() {
                RunInMain.dispatch(new Runnable() {
                    @Override
                    public void run() {
                        //这样它就回到主线程运行了
                        Toast.makeText(MainActivity.this, "弹个Toast", Toast.LENGTH_SHORT).show();
                    }
                });
            }
        }).start();

这样子弹Toast也是没有任何问题的

猜你喜欢

转载自blog.csdn.net/simplebam/article/details/78442046
今日推荐