| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 移动开发 -> 实现多线程的四种方式与线程池原理 -> 正文阅读 |
|
[移动开发]实现多线程的四种方式与线程池原理 |
实现多线程的三种方法:(1)继承Thread类,(2)实现Runnable接口,(3)实现Callable接口 方法一:继承Thread类?重写run方法,调用对象的start()注意:如果是tt.run()不能开启多线程,相当于调用TestThread类的run()方法,这是一种“同步编程模型”
方法二:实现Runnable接口,重写run方法,调用实现类的start方法
方式三:实现Callable接口 重写call()方法我们知道,实现Runnable接口的时候,需要重写run方法,也就是线程在启动的时候,会自动调用的方法 同理,我们实现Callable接口,也需要实现call方法,但是这个时候我们还需要有返回值,这个Callable接口的应用场景一般就在于批处理业务,比如转账的时候,需要给一会返回结果的状态码回来,代表本次操作成功还是失败 /** * Callable有返回值 * 批量处理的时候,需要带返回值的接口(例如支付失败的时候,需要返回错误状态) * */ class MyThread2 implements Callable<Integer> { @Override public Integer call() throws Exception { System.out.println("come in Callable"); return 1024; } } 最后我们需要做的就是通过Thread线程, 将MyThread2实现Callable接口的类包装起来 这里需要用到的是FutureTask类,他实现了Runnable接口,并且还需要传递一个实现Callable接口的类作为构造函数 // FutureTask:实现了Runnable接口,构造函数又需要传入 Callable接口 // 这里通过了FutureTask接触了Callable接口 FutureTask<Integer> futureTask = new FutureTask<>(new MyThread2()); 然后在用Thread进行实例化,传入实现Runnabnle接口的FutureTask的类 Thread t1 = new Thread(futureTask, "aaa"); t1.start(); 最后通过 futureTask.get() 获取到返回值 // 输出FutureTask的返回值 System.out.println("result FutureTask " + futureTask.get()); 这就相当于原来我们的方式是main方法一条龙之心,后面在引入Callable后,对于执行比较久的线程,可以单独新开一个线程进行执行,最后在进行汇总输出 最后需要注意的是 要求获得Callable线程的计算结果,如果没有计算完成就要去强求,会导致阻塞,直到计算完成 注意多个线程执行 一个FutureTask的时候,只会计算一次 FutureTask<Integer> futureTask = new FutureTask<>(new MyThread2()); // 开启两个线程计算futureTask new Thread(futureTask, "AAA").start(); new Thread(futureTask, "BBB").start(); 如果我们要两个线程同时计算任务的话,那么需要这样写,需要定义两个futureTask FutureTask<Integer> futureTask = new FutureTask<>(new MyThread2()); FutureTask<Integer> futureTask2 = new FutureTask<>(new MyThread2()); // 开启两个线程计算futureTask new Thread(futureTask, "AAA").start(); new Thread(futureTask2, "BBB").start(); 方法四:创建线程池
具体使用,首先我们需要使用Executors工具类,进行创建线程池,这里创建了一个拥有5个线程的线程池
我们需要使用 threadPool.execute执行业务,execute需要传入一个实现了Runnable接口的线程 或者使用threadPool.submit(),里面可以传入runnable接口,也可以传入callable接口。 threadPool.execute(() -> { System.out.println(Thread.currentThread().getName() + "\t 给用户办理业务"); }); 然后我们使用完毕后关闭线程池 threadPool.shutdown();
线程池的七大参数:通过Executors类名,调用静态方法:newFixedThreadPool()创建线程,表面是五参数 通过五参数的构造方法,传入五个参数,调用this(),进入七参数的构造方法。? ? 线程池在创建的时候,一共有7大参数(先看线线程池底层工作原理更好理解)
线程池底层工作原理:线程池运行架构图 文字说明
以顾客去银行办理业务为例,谈谈线程池的底层工作原理
? 拒绝策略以下所有拒绝策略都实现了RejectedExecutionHandler接口
? 为什么不用默认创建的线程池?线程池创建的方法有:固定数的,单一的,可变的,那么在实际开发中,应该使用哪个? 我们一个都不用,在生产环境中是使用自己自定义的 为什么不用 Executors 中JDK提供的? 根据阿里巴巴手册:并发控制这章
线程池的合理参数生产环境中如何配置 corePoolSize 和 maximumPoolSize 这个是根据具体业务来配置的,分为CPU密集型和IO密集型
CPU密集的意思是该任务需要大量的运算,而没有阻塞,CPU一直全速运行 CPU密集任务只有在真正的多核CPU上才可能得到加速(通过多线程) 而在单核CPU上,无论你开几个模拟的多线程该任务都不可能得到加速,因为CPU总的运算能力就那些 CPU密集型任务配置尽可能少的线程数量: 一般公式:CPU核数 + 1个线程数
由于IO密集型任务线程并不是一直在执行任务,则可能多的线程,如 CPU核数 * 2 IO密集型,即该任务需要大量的IO操作,即大量的阻塞 在单线程上运行IO密集型的任务会导致浪费大量的CPU运算能力花费在等待上 所以IO密集型任务中使用多线程可以大大的加速程序的运行,即使在单核CPU上,这种加速主要就是利用了被浪费掉的阻塞时间。 IO密集时,大部分线程都被阻塞,故需要多配置线程数: 参考公式:CPU核数 / (1 - 阻塞系数) 阻塞系数在0.8 ~ 0.9左右 例如:8核CPU:8/ (1 - 0.9) = 80个线程数 |
|
移动开发 最新文章 |
Vue3装载axios和element-ui |
android adb cmd |
【xcode】Xcode常用快捷键与技巧 |
Android开发中的线程池使用 |
Java 和 Android 的 Base64 |
Android 测试文字编码格式 |
微信小程序支付 |
安卓权限记录 |
知乎之自动养号 |
【Android Jetpack】DataStore |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
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年11日历 | -2024/11/24 22:43:00- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |