实践-创建多少线程合适

创建多少线程合适?

根据文章Java线程(中):创建多少线程才是合适的?

我总结了

  • 为什么要使用多线程?

    因为程序执行多任务时,可以执行的更快,快 取决于 延迟吞吐量 。降低延迟,提高吞吐量

  • 多线程的应用场景有哪些?
    io密集型:磁盘和内存打交道之类的操作
    cpu密集型:复杂计算,几乎不操作磁盘,就是一个劲的计算

  • 线程数如何创建?

    cpu密集型 线程数和cpu核数相等就行(不过在工程上,线程的数量一般会设置为“CPU 核数 +1”),为什么呢?

    1. 假设只有cpu计算,io操作很少甚至没有的一个场景;

      • 线程数如果少于cpu核数,如果计算量充足的情况下,每个线程都是正常工作,没有线程切换,但是存在cpu核没有利用到的情况,这是cpu利用率不足。
      • 线程数如果多于CPU核数,如果计算量充足的情况下,那么多出来的线程会争抢CPU资源,造成线程切换的成本。

​ io密集型 最佳线程数 =CPU 核数 * [ 1 +(I/O 耗时 / CPU 耗时)] (工程上,一般是cpu核数*2+1
20220706173915

针对io密集型和cpu密集型的合适线程数实践

本机配置

20220706174229

实验代码

/**
 * @author ggBall
 * @version 1.0.0
 * @ClassName IoTest.java
 * @Description TODO
 * @createTime 2022年07月06日 14:48:00
 */
public class PerformanceTest {

    String classFilePath = PerformanceTest.class.getResource("").getPath();

    CountDownLatch latch;

    /**
     * 按照公式 io密集型 线程数=核数*2+1 本机8核 线程数应该是17
     * 结果 20次的10000次io操作 (8核*2+1)10个线程操作 平均1705.3ms
     * 结果 20次的10000次io操作 (8核*2+1)11个线程操作 平均1605.35ms
     * 结果 20次的10000次io操作 (8核*2+1)12个线程操作 平均1595.45ms
     * 结果 20次的10000次io操作 (8核*2+1)13个线程操作 平均1625.1ms
     * 结果 20次的10000次io操作 (8核*2+1)14个线程操作 平均1648.65ms
     * 结果 20次的10000次io操作 (8核*2+1)15个线程操作 平均1654.95ms
     * 结果 20次的10000次io操作 (8核*2+1)16个线程操作 平均1655.3ms
     * 结果 20次的10000次io操作 (8核*2+1)17个线程操作 平均1645.5ms
     * 结果 20次的10000次io操作 (8核*2+1)18个线程操作 平均1645.6ms
     * 结果 20次的10000次io操作 (8核*2+1)19个线程操作 平均1661.35ms
     * 结果 20次的10000次io操作 (8核*2+1)20个线程操作 平均1675.95ms
     * @throws InterruptedException
     */
    @Test
    public void ioTest() throws InterruptedException {

        int ioTimes = 10000;
        int threadNum;
        for (int i1 = 10; i1 <= 20; i1++) {
            threadNum = i1;
            ArrayList<Long> times = new ArrayList<>();
            for (int i = 0; i < 20; i++) {
                long time = singleIo(ioTimes, threadNum);
                times.add(time);
            }
            Double avgTime = times.stream().collect(Collectors.averagingLong(item -> item));
//            System.out.println(times);
            System.out.println("结果 20次的"+ioTimes+"次io操作 (8核*2+1)"+threadNum+"个线程操作 平均"+avgTime+"ms");
        }



    }

    /**
     * 按照公式 cpu密集型 线程数=核数 本机8核 线程数应该是8
     * 结果 20次的10000次cpu操作 (8核*2+1)15个线程操作 平均2.0ms
     * 结果 20次的10000次cpu操作 (8核*2+1)14个线程操作 平均1.85ms
     * 结果 20次的10000次cpu操作 (8核*2+1)13个线程操作 平均2.0ms
     * 结果 20次的10000次cpu操作 (8核*2+1)12个线程操作 平均1.6ms
     * 结果 20次的10000次cpu操作 (8核*2+1)11个线程操作 平均1.5ms
     * 结果 20次的10000次cpu操作 (8核*2+1)10个线程操作 平均1.6ms
     * 结果 20次的10000次cpu操作 (8核*2+1)9个线程操作 平均1.55ms
     * 结果 20次的10000次cpu操作 (8核*2+1)8个线程操作 平均1.35ms
     * 结果 20次的10000次cpu操作 (8核*2+1)7个线程操作 平均1.4ms
     * 结果 20次的10000次cpu操作 (8核*2+1)6个线程操作 平均1.6ms
     * 结果 20次的10000次cpu操作 (8核*2+1)5个线程操作 平均1.45ms
     * 结果 20次的10000次cpu操作 (8核*2+1)4个线程操作 平均1.4ms
     * 结果 20次的10000次cpu操作 (8核*2+1)3个线程操作 平均1.0ms
     * 结果 20次的10000次cpu操作 (8核*2+1)2个线程操作 平均1.7ms
     * @throws InterruptedException
     */
    @Test
    public void cpuTest() throws InterruptedException {
        int cpuTimes = 10000;
        int threadNum;
        for (int i1 = 16; i1 > 1; i1--) {
            threadNum = i1;
            ArrayList<Long> times = new ArrayList<>();
            for (int i = 0; i < 20; i++) {
                long time = singleCPU(cpuTimes, threadNum);
                times.add(time);
            }
            Double avgTime = times.stream().collect(Collectors.averagingLong(item -> item));
//            System.out.println(times);
            System.out.println("结果 20次的"+cpuTimes+"次cpu操作 (8核*2+1)"+threadNum+"个线程操作 平均"+avgTime+"ms");
        }

    }

    /**
     * 执行单次多线程cpu任务
     * @param cpuTimes
     * @param threadNum
     * @return
     * @throws InterruptedException
     */
    private long singleCPU(int cpuTimes, int threadNum) throws InterruptedException {

        latch = new CountDownLatch(cpuTimes);

        long start = System.currentTimeMillis();
        // 170次io操作 (8核*2+1)17个线程操作
        ExecutorService executorService = Executors.newFixedThreadPool(threadNum);

        for (int i = 0; i < cpuTimes; i++) {
            CPUTasker tasker = new CPUTasker();
            executorService.submit(tasker);
        }

        latch.await();

        long end = System.currentTimeMillis();

//        System.out.println(end-start+"ms");
        return end-start;
    }


    /**
     * 执行单次多线程io任务
     * @param ioTimes
     * @param threadNum
     * @return
     * @throws InterruptedException
     */
    public long singleIo(int ioTimes,int threadNum) throws InterruptedException {
        latch = new CountDownLatch(ioTimes);

        long start = System.currentTimeMillis();
        // 170次io操作 (8核*2+1)17个线程操作
        ExecutorService executorService = Executors.newFixedThreadPool(threadNum);

        for (int i = 0; i < ioTimes; i++) {
            IoTasker tasker = new IoTasker();
            executorService.submit(tasker);
        }

        latch.await();

        long end = System.currentTimeMillis();

//        System.out.println(end-start+"ms");
        return end-start;
    }

    /**
     * io任务
     */
    class IoTasker implements Runnable{

        @Override
        public void run() {
            String fileName = "text.txt";
            FIleUtils fIleUtils = new FIleUtils();
            fIleUtils.writeFile(classFilePath+ "/" + fileName,"sda实打实大sss11212");
            try {
                fIleUtils.fileRead(classFilePath+ "/" + fileName);
//                System.out.println(Thread.currentThread().getName()+"io完成");
                latch.countDown();

            } catch (NoSuchFieldException e) {
                throw new RuntimeException(e);
            }
        }
    }

    /**
     * cpu任务
     */
    class CPUTasker implements Runnable{

        @Override
        public void run() {
            for (int i = 0; i < 1024; i++) {
                for (int j = 0; j < 1024; j++) {
                    for (int k = 0; k < 1024; k++) {
                        
                    }
                }
            }
            latch.countDown();
        }
    }


}


实践总结

从实验代码看,io密集型设置的线程数 确实符合 线程数=核数*2+1 公式,测试结果显示17个线程耗时最少;但是cpu密集型 从线程数3~12个 耗时都在1.5ms左右,与公式线程数=核数相差很大,
所以设置线程的公式只是参考标准,生产环境还得实际测试

问题

实践总结

从实验代码看,io密集型设置的线程数 确实符合 线程数=核数*2+1 公式,测试结果显示17个线程耗时最少;但是cpu密集型 从线程数3~12个 耗时都在1.5ms左右,与公式线程数=核数相差很大,
所以设置线程的公式只是参考标准,生产环境还得实际测试

问题

I/O 耗时 和 CPU 耗时 不知道使用什么工具测试?

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
《Android开发艺术探索》是一本Android进阶类书籍,采用理论、源码和实践相结合的方式来阐述高水准的Android应用开发要点。《Android开发艺术探索》从三个方面来组织内容。第一,介绍Android开发者不容易掌握的一些知识点;第二,结合Android源代码和应用层开发过程,融会贯通,介绍一些比较深入的知识点;第三,介绍一些核心技术和Android的性能优化思想。 《Android开发艺术探索》侧重于Android知识的体系化和系统工作机制的分析,通过《Android开发艺术探索》的学习可以极大地提高开发者的Android技术水平,从而更加高效地成为高级开发者。而对于高级开发者来说,仍然可以从《Android开发艺术探索》的知识体系中获益。 全书目录 ------------------------------------------------------------------- 第1章 Activity的生命周期和启动模式 / 1   1.1 Activity的生命周期全面分析 / 1   1.1.1 典型情况下的生命周期分析 / 2   1.1.2 异常情况下的生命周期分析 / 8   1.2 Activity的启动模式 / 16   1.2.1 Activity的LaunchMode / 16   1.2.2 Activity的Flags / 27   1.3 IntentFilter的匹配规则 / 28   第2章 IPC机制 / 35   2.1 Android IPC简介 / 35   2.2 Android中的多进程模式 / 36   2.2.1 开启多进程模式 / 36   2.2.2 多进程模式的运行机制 / 39   2.3 IPC基础概念介绍 / 42   2.3.1 Serializable接口 / 42   2.3.2 Parcelable接口 / 45   2.3.3 Binder / 47   2.4 Android中的IPC方式 / 61   2.4.1 使用Bundle / 61   2.4.2 使用文件共享 / 62   2.4.3 使用Messenger / 65   2.4.4 使用AIDL / 71   2.4.5 使用ContentProvider / 91   2.4.6 使用Socket / 103   2.5 Binder连接池 / 112   2.6 选用合适的IPC方式 / 121   第3章 View的事件体系 / 122   3.1 View基础知识 / 122   3.1.1 什么是View / 123   3.1.2 View的位置参数 / 123   3.1.3 MotionEvent和TouchSlop / 125   3.1.4 VelocityTracker、GestureDetector和Scroller / 126   3.2 View的滑动 / 129   3.2.1 使用scrollTo/scrollBy / 129   3.2.2 使用动画 / 131   3.2.3 改变布局参数 / 133   3.2.4 各种滑动方式的对比 / 133   3.3 弹性滑动 / 135   3.3.1 使用Scroller / 136   3.3.2 通过动画 / 138   3.3.3 使用延时策略 / 139   3.4 View的事件分发机制 / 140   3.4.1 点击事件的传递规则 / 140   3.4.2 事件分发的源码解析 / 144   3.5 View的滑动冲突 / 154   3.5.1 常见的滑动冲突场景 / 155   3.5.2 滑动冲突的处理规则 / 156   3.5.3 滑动冲突的解决方式 / 157   第4章 View的工作原理 / 174   4.1 初识ViewRoot和DecorView / 174   4.2 理解MeasureSpec / 177   4.2.1 MeasureSpec / 177   4.2.2 MeasureSpec和LayoutParams的对应关系 / 178   4.3 View的工作流程 / 183   4.3.1 measure过程 / 183   4.3.2 layout过程 / 193   4.3.3 draw过程 / 197   4.4 自定义View / 199   4.4.1 自定义View的分类 / 200   4.4.2 自定义View须知 / 201   4.4.3 自定义View示例 / 202   4.4.4 自定义View的思想 / 217   第5章 理解RemoteViews / 218   5.1 RemoteViews的应用 / 218   5.1.1 RemoteViews在通知栏上的应用 / 219   5.1.2 RemoteViews在桌面小部件上的应用 / 221   5.1.3 PendingIntent概述 / 228   5.2 RemoteViews的内部机制 / 230   5.3 RemoteViews的意义 / 239   第6章 Android的Drawable / 243   6.1 Drawable简介 / 243   6.2 Drawable的分类 / 244   6.2.1 BitmapDrawable / 244   6.2.2 ShapeDrawable / 247   6.2.3 LayerDrawable / 251   6.2.4 StateListDrawable / 253   6.2.5 LevelListDrawable / 255   6.2.6 TransitionDrawable / 256   6.2.7 InsetDrawable / 257   6.2.8 ScaleDrawable / 258   6.2.9 ClipDrawable / 260   6.3 自定义Drawable / 262   第7章 Android动画深入分析 / 265   7.1 View动画 / 265   7.1.1 View动画的种类 / 265   7.1.2 自定义View动画 / 270   7.1.3 帧动画 / 272   7.2 View动画的特殊使用场景 / 273   7.2.1 LayoutAnimation / 273   7.2.2 Activity的切换效果 / 275   7.3 属性动画 / 276   7.3.1 使用属性动画 / 276   7.3.2 理解插值器和估值器 / 280   7.3.3 属性动画的监听器 / 282   7.3.4 对任意属性做动画 / 282   7.3.5 属性动画的工作原理 / 288   7.4 使用动画的注意事项 / 292   第8章 理解Window和WindowManager / 294   8.1 Window和WindowManager / 294   8.2 Window的内部机制 / 297   8.2.1 Window的添加过程 / 298   8.2.2 Window的删除过程 / 301   8.2.3 Window的更新过程 / 303   8.3 Window的创建过程 / 304   8.3.1 Activity的Window创建过程 / 304   8.3.2 Dialog的Window创建过程 / 308   8.3.3 Toast的Window创建过程 / 311   第9章 四大组件的工作过程 / 316   9.1 四大组件的运行状态 / 316   9.2 Activity的工作过程 / 318   9.3 Service的工作过程 / 336   9.3.1 Service的启动过程 / 336   9.3.2 Service的绑定过程 / 344   9.4 BroadcastReceiver的工作过程 / 352   9.4.1 广播的注册过程 / 353   9.4.2 广播的发送和接收过程 / 356   9.5 ContentProvider的工作过程 / 362   第10章 Android的消息机制 / 372   10.1 Android的消息机制概述 / 373   10.2 Android的消息机制分析 / 375   10.2.1 ThreadLocal的工作原理 / 375   10.2.2 消息队列的工作原理 / 380   10.2.3 Looper的工作原理 / 383   10.2.4 Handler的工作原理 / 385   10.3 主线程的消息循环 / 389   第11章 Android的线程和线程池 / 391   11.1 主线程和子线程 / 392   11.2 Android中的线程形态 / 392   11.2.1 AsyncTask / 392   11.2.2 AsyncTask的工作原理 / 395   11.2.3 HandlerThread / 402   11.2.4 IntentService / 403   11.3 Android中的线程池 / 406   11.3.1 ThreadPoolExecutor / 407   11.3.2 线程池的分类 / 410   第12章 Bitmap的加载和Cache / 413   12.1 Bitmap的高效加载 / 414   12.2 Android中的缓存策略 / 417   12.2.1 LruCache / 418   12.2.2 DiskLruCache / 419   12.2.3 ImageLoader的实现 / 424   12.3 ImageLoader的使用 / 441   12.3.1 照片墙效果 / 441   12.3.2 优化列表的卡顿现象 / 446   第13章 综合技术 / 448   13.1 使用CrashHandler来获取应用的crash信息 / 449   13.2 使用multidex来解决方法数越界 / 455   13.3 Android的动态加载技术 / 463   13.4 反编译初步 / 469   13.4.1 使用dex2jar和jd-gui反编译apk / 470   13.4.2 使用apktool对apk进行二次打包 / 470   第14章 JNI和NDK编程 / 473   14.1 JNI的开发流程 / 474   14.2 NDK的开发流程 / 478   14.3 JNI的数据类型和类型签名 / 484   14.4 JNI调用Java方法的流程 / 486   第15章 Android性能优化 / 489   15.1 Android的性能优化方法 / 490   15.1.1 布局优化 / 490   15.1.2 绘制优化 / 493   15.1.3 内存泄露优化 / 493   15.1.4 响应速度优化和ANR日志分析 / 496   15.1.5 ListView和Bitmap优化 / 501   15.1.6 线程优化 / 501   15.1.7 一些性能优化建议 / 501   15.2 内存泄露分析之MAT工具 / 502   15.3 提高程序的可维护性 / 506
《OPhone应用开发权威指南》2010 黄晓庆 博文视点 broadview 第1章 OPhone平台概述 1 1.1 OPhone的架构 1 1.1.1 Linux内核 2 1.1.2 本地库 2 1.1.3 OPhone运行环境 3 1.1.4 Widget运行环境 3 1.1.5 应用程序框架 4 1.1.6 应用程序 5 1.2 开发OPhone应用程序 5 1.2.1 开发语言 5 1.2.2 OPhone SDK 5 1.2.3 OPhone开发者社区 6 1.3 将OPhone应用上传到Mobile Market 7 1.3.1 Mobile Market的商业模式 7 1.3.2 Mobile Market发布流程 8 1.4 小结 11 第2章 OPhone开发环境和流程 12 2.1 安装Eclipse和ODT 12 2.1.1 安装Java SDK 12 2.1.2 安装Eclipse 13 2.1.3 安装OPhone SDK 13 2.1.4 安装和配置ODT插件 14 2.2 第一个OPhone应用程序 16 2.2.1 新建OPhone项目 16 2.2.2 运行OPhone项目 18 2.2.3 更新资源文件 21 2.3 调试OPhone应用程序 24 2.3.1 设置断点 25 2.3.2 启动调试 25 2.3.3 单步跟踪 26 2.4 在命令行下开发OPhone程序 27 2.4.1 创建项目 27 2.4.2 用Ant编译项目 28 2.4.3 运行应用程序 28 2.5 OPhone SDK介绍 30 2.5.1 OPhone模拟器 30 2.5.2 模拟SD卡 32 2.5.3 ADB 32 2.5.4 DDMS 33 2.6 小结 34 第3章 OPhone应用程序模型 35 3.1 OPhone应用程序基础 35 3.1.1 OPhone应用程序运行环境 35 3.1.2 OPhone应用程序的组成 36 3.2 Activity 43 3.2.1 Activity创建与声明 44 3.2.2 Activity的生命周期 48 3.2.3 启动Activity 55 3.2.4 Activity和Task 58 3.3 Content Provider 61 3.4 BroadcastReceiver 64 3.5 Service 66 3.6 安全与许可 66 3.6.1 安全架构 66 3.6.2 许可 67 3.7 数字签名 70 3.7.1 签名策略 70 3.7.2 签名步骤 71 3.8 小结 72 第4章 图形用户界面 73 4.1 用户界面概述 73 4.1.1 手机软硬件特性的发展 73 4.1.2 如何影响应用程序开发 74 4.1.3 OPhone图形引擎 74 4.2 用户界面设计 75 4.2.1 声明布局文件 75 4.2.2 编写XML文件 75 4.2.3 加载XML文件 76 4.2.4 将数据绑定到AdapterView 77 4.2.5 创建菜单 79 4.2.6 创建Dialog 81 4.2.7 通知用户 83 4.2.8 处理用户输入 84 4.2.9 样式与主题 84 4.3 常用Widget 86 4.3.1 TextView 86 4.3.2 Button 89 4.3.3 ImageView 90 4.3.4 ProgressBar 92 4.3.5 DatePicker/TimePicker 94 4.3.6 GridView 96 4.3.7 Spinner 98 4.3.8 Gallery 100 4.3.9 TabHost 101 4.4 高级图形用户界面技术 104 4.4.1 图形系统类结构 104 4.4.2 常用布局类 107 4.4.3 绘制图形 114 4.4.4 构建自己的组件 123 4.5 图形动画 130 4.5.1 Animation 131 4.5.2 Interpolator 136 4.5.3 AnimationSet 137 4.5.4 自定义动画 138 4.6 Resource介绍 143 4.6.1 资源类型 143 4.6.2 使用资源 144 4.6.3 资源适配 146 4.7 俄罗斯方块实例 147 4.7.1 方块的数据结构 147 4.7.2 方块渲染 150 4.7.3 游戏区域设计 152 4.7.4 碰撞检测 156 4.7.5 输入处理 158 4.7.6 积分排行榜 160 4.8 小结 161 第5章 OpenGL ES编程 162 5.1 OpenGL ES概述 162 5.1.1 OpenGL ES设计准则 162 5.1.2 OpenGL ES 与OpenGL的不同 163 5.1.3 一个简单的OpenGL ES程序 166 5.2 3D观察与变换 169 5.2.1 一个简单的例子:绘制立方体 169 5.2.2 理解变换 175 5.2.3 投影变换 177 5.2.4 视口变换 179 5.2.5 矩阵堆栈 180 5.3 绘制图元 180 5.3.1 图元种类 180 5.3.2 指定顶点数据 182 5.3.3 绘制图元 186 5.4 颜色和光照 186 5.4.1 设置颜色和材质 187 5.4.2 光照 188 5.5 光栅化和片元处理 193 5.5.1 背面剪裁 193 5.5.2 纹理映射 193 5.5.3 雾 205 5.5.4 反走样 207 5.5.5 像素测试 209 5.5.6 将片元合并到颜色缓存 212 5.6 帧缓存操作 216 5.6.1 清空缓存 216 5.6.2 读取颜色缓存 216 5.6.3 强制完成绘图指令 217 5.7 其他 217 5.7.1 行为控制函数 217 5.7.2 状态查询 218 5.8 EGL简介 218 5.9 小结 222 第6章 数据持久化存储 223 6.1 文件存储 223 6.1.1 存储至默认文件夹 224 6.1.2 存储至指定文件夹 226 6.1.3 存储至SD卡 227 6.1.4 读取资源文件 228 6.2 SharePreference 229 6.3 SQLite 233 6.3.1 创建数据库 234 6.3.2 SQLiteOpenHelper 236 6.3.3 创建触发器 240 6.3.4 创建索引 241 6.3.5 创建视图 241 6.3.6 操作数据 243 6.3.7 将Cursor绑定到AdapterView 250 6.4 Content Provider 254 6.4.1 概述 254 6.4.2 Content Provider加载机制 256 6.4.3 创建Content Provider 257 6.4.4 Content Provider更新的通知机制 267 6.4.5 DAO接口及实现 269 6.4.6 在新线程内处理数据 270 6.5 小结 273 第7章 移动多媒体编程 274 7.1 多媒体文件格式与编码 274 7.1.1 多媒体文件格式 274 7.1.2 编码 275 7.1.3 OPhone平台支持的媒体格式 276 7.1.4 选择合适的媒体文件 277 7.2 音频和视频播放 277 7.2.1 三种不同的数据源 278 7.2.2 MediaPlayer的状态 281 7.2.3 音乐播放器实例 284 7.2.4 播放视频 296 7.3 录制音频 299 7.3.1 MediaRecorder的状态图 299 7.3.2 录音器实例 301 7.4 MP3文件格式分析 306 7.4.1 MP3文件介绍 307 7.4.2 ID3V1标签 307 7.4.3 ID3V2标签 310 7.4.4 MP3帧结构 316 7.4.5 分割MP3文件 323 7.5 案例分析——铃声DIY 327 7.6 小结 329 第8章 让程序在后台运行 330 8.1 Service概述 330 8.2 Service编程实践 331 8.2.1 创建Service 331 8.2.2 启动和停止Service 333 8.2.3 通知用户 335 8.2.4 不阻塞用户操作 337 8.2.5 Service与Activity通信 343 8.3 后台播放音乐 345 8.3.1 跨进程调用 345 8.3.2 创建AIDL接口文件 346 8.3.3 实现AIDL接口 347 8.3.4 绑定Service 351 8.3.5 调用IPC方法 352 8.4 小结 353 第9章 访问网络数据和服务 354 9.1 HTTP协议简介 354 9.1.1 HTTP协议的主要特点 354 9.1.2 HTTP连接过程 355 9.1.3 HTTP消息格式 355 9.2 线程管理 358 9.2.1 匿名Thread 358 9.2.2 java.util.concurrent框架 359 9.2.3 AsyncTask 369 9.3 网络编程接口 373 9.3.1 HttpClient API介绍 373 9.3.2 GET方法的使用和限制 378 9.3.3 使用POST方法上传附件 382 9.3.4 从服务器端下载图片 390 9.4 设计C/S通信数据格式 392 9.4.1 对象序列化 396 9.4.2 使用XML传输对象 401 9.5 小结 409 第10章 高级通信技术 410 10.1 电话 410 10.1.1 电话呼叫 410 10.1.2 监听电话状态 412 10.1.3 查询电话属性 416 10.1.4 读取通话记录 416 10.2 短消息 420 10.2.1 发送短信 421 10.2.2 接收短消息 423 10.3 小结 426 第11章 访问硬件层 427 11.1 访问相机 427 11.1.1 创建Camera对象 427 11.1.2 设置Camera参数 428 11.1.3 预览 429 11.1.4 拍摄照片 429 11.2 访问位置服务 431 11.2.1 创建LocationManager 431 11.2.2 LocationProvider类 432 11.2.3 监听位置更新 433 11.2.4 接近警报 434 11.3 访问传感器 435 11.3.1 SensorManager类 435 11.3.2 监听传感器事件 436 11.3.3 方向传感器应用—指南针 437 11.3.4 模拟传感器 440 11.4 小结 443 附录A 如何导入源代码 444 附录B Resin安装与Servlet部署 446 参考文献 450
本书是一本Android进阶类书籍,采用理论、源码和实践相结合的方式来阐述高水准的Android应用开发要点。本书从三个方面来组织内容。第一,介绍Android开发者不容易掌握的一些知识点;第二,结合Android源代码和应用层开发过程,融会贯通,介绍一些比较深入的知识点;第三,介绍一些核心技术和Android的性能优化思想。 第1章 Activity的生命周期和启动模式 1 1.1 Activity的生命周期全面分析 1 1.1.1 典型情况下的生命周期分析 2 1.1.2 异常情况下的生命周期分析 8 1.2 Activity的启动模式 16 1.2.1 Activity的LaunchMode 16 1.2.2 Activity的Flags 27 1.3 IntentFilter的匹配规则 28 第2章 IPC机制 35 2.1 Android IPC简介 35 2.2 Android中的多进程模式 36 2.2.1 开启多进程模式 36 2.2.2 多进程模式的运行机制 39 2.3 IPC基础概念介绍 42 2.3.1 Serializable接口 42 2.3.2 Parcelable接口 45 2.3.3 Binder 47 2.4 Android中的IPC方式 61 2.4.1 使用Bundle 61 2.4.2 使用文件共享 62 2.4.3 使用Messenger 65 2.4.4 使用AIDL 71 2.4.5 使用ContentProvider 91 2.4.6 使用Socket 103 2.5 Binder连接池 112 2.6 选用合适的IPC方式 121 第3章 View的事件体系 122 3.1 View基础知识 122 3.1.1 什么是View 123 3.1.2 View的位置参数 123 3.1.3 MotionEvent和TouchSlop 125 3.1.4 VelocityTracker、GestureDetector和Scroller 126 3.2 View的滑动 129 3.2.1 使用scrollTo/scrollBy 129 3.2.2 使用动画 131 3.2.3 改变布局参数 133 3.2.4 各种滑动方式的对比 133 3.3 弹性滑动 135 3.3.1 使用Scroller 136 3.3.2 通过动画 138 3.3.3 使用延时策略 139 3.4 View的事件分发机制 140 3.4.1 点击事件的传递规则 140 3.4.2 事件分发的源码解析 144 3.5 View的滑动冲突 154 3.5.1 常见的滑动冲突场景 155 3.5.2 滑动冲突的处理规则 156 3.5.3 滑动冲突的解决方式 157 第4章 View的工作原理 174 4.1 初识ViewRoot和DecorView 174 4.2 理解MeasureSpec 177 4.2.1 MeasureSpec 177 4.2.2 MeasureSpec和LayoutParams的对应关系 178 4.3 View的工作流程 183 4.3.1 measure过程 183 4.3.2 layout过程 193 4.3.3 draw过程 197 4.4 自定义View 199 4.4.1 自定义View的分类 200 4.4.2 自定义View须知 201 4.4.3 自定义View示例 202 4.4.4 自定义View的思想 217 第5章 理解RemoteViews 218 5.1 RemoteViews的应用 218 5.1.1 RemoteViews在通知栏上的应用 219 5.1.2 RemoteViews在桌面小部件上的应用 221 5.1.3 PendingIntent概述 228 5.2 RemoteViews的内部机制 230 5.3 RemoteViews的意义 239 第6章 Android的Drawable 243 6.1 Drawable简介 243 6.2 Drawable的分类 244 6.2.1 BitmapDrawable 244 6.2.2 ShapeDrawable 247 6.2.3 LayerDrawable 251 6.2.4 StateListDrawable 253 6.2.5 LevelListDrawable 255 6.2.6 TransitionDrawable 256 6.2.7 Ins

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值