安卓并发编程基础

article/2025/9/20 21:25:34

在这里插入图片描述

1.线程

1.线程与进程的区别。

进程是程序运行和资源分配的基本单位,一个程序至少有一个进程,一个进程至少有一个线程。进程在执行过程中拥有独立的内存单元,而多个线程共享内存资源,减少切换次数,从而效率更高。线程是进程的一个实体,是cpu调度和分派的基本单位,是比程序更小的能独立运行的基本单位。同一进程中的多个线程之间可以并发执行。

2.创建线程的几种方式

  • 1.通过 new Thread的方式创建,可复写 Thread#run方法,Thread.start()方式启动。

  • 2.实现Runnable接口,通过Thread调用。

  • 3.实现 Callable 接口 ,封装 FutureTask 创建线程的 target 对象。
    在这里插入图片描述

可以获取线程的执行状态,get方法会阻塞线程,及取消线程。
对比:2 和 3 适合多个线程处理同一份资源的情况。

3.Android中异步任务的执行方式

  • new Thread

    • 缺点:缺乏统一管理,可能无限创建线程,相互竞争,占用过多系统资源导致死机或oom
  • AsyncTask

    • 轻量级异步任务工具,提供执行任务的进度回调给 UI 线程
    • 场景:适用于需要知道任务执行的进度,多个任务串行执行
    • 缺点:生命周期不同步,容易造成内存泄露,默认情况所有任务串行执行
    //1.串行执行,内部使用 SERIAL_EXECUTOR 执行任务
    AsyncTask.execute(runnable);
    AsyncTask.SERIAL_EXECUTOR.execute(runnable);
    //2.可并发执行的线程池AsyncTask.THREAD_POOL_EXECUTOR.execute(runnable);
    
  • HandlerThread

    • 适用于主线程需要和工作线程通信,持续性任务,比如轮询等场景,所有任务串行执行
    • 缺点:不会向普通线程一样主动销毁,需要手动销毁,否则造成内存泄露
  • IntentSerivice

    • 子线程执行任务,任务执行完后自我结束,不需要手动 stopService
  • ThreadPoolExecutor

    • 适用于处理大量耗时较短的任务场景
Executors.newCachedThreadPool();//线程可复用的线程池
Executors.newFixedThreadPool();//固定数量的线程池
Executors.newScheduledThreadPool();//可指定定时任务的线程池
Executors.newSingleThreadExecutor();//线程数量为1的线程池

4.线程的优先级

线程的优先级具有继承性,在某个线程中创建的线程会继承次线程的优先级。

  • JDK Api 限制了新设置的线程优先级为[1~10],优先级越高,获取 CPU 时间片的概率越高,UI 线程优先级为 5。
  • Android Api,可设置线程优先级为[-20 ~ 19],优先级越低,获取 CPU时间片的概率越高,UI为 -10。

5.线程的几种状态

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JGpP3c2o-1634264627400)(../../pic/1628091886021.png)]
在这里插入图片描述
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-2FR1j3So-1634264627403)(../../pic/image-20210831155345858.png)]

2.线程并发安全

1.什么是线程安全?

线程安全的本质是能够让并发线程有序的运行 (这个有序有可能是先来后到的排队,有可能有人插队,不论怎样,同一时刻只能一个线程有访问同步资源),执行的结果,能够对其他线程可见。

2.线程安全的分类

  • synchronized 关键字
  • ReentrantLock 锁
  • AtomicInteger… 原子类

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vIcfdShb-1634264627404)(../../pic/image-20211014192218978.png)]

3.锁的对比

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fydBy5IT-1634264627405)(../../pic/image-20211014192645562.png)]

  • 锁适合写操作多的场景,先加锁可以保证写操作的时数据的正确性。
  • 原子类适合读操作多的场景,不加锁的特点能够使其读操作性能大幅度提升。

3.如何保证线程安全

AtomicInteger 原子包装类,采用 CAS (Compare-And-Swap) 实现无锁的数据更新,自旋的设计能够有效避免线程因阻塞-唤醒带来的系统资源开销
适用场景:多线程计数,原子操作,并发数量小的场景

Volatile 关键字

volatile 修饰的成员变量在每次被线程访问的时候,都强迫从共享内存重新读取该成员变量的值,而且,当成员变量的值发生变化的时,强迫将变化的值重新写入共享内存中。

注意:不能解决非原子操作的安全性。性能不及原子类高。

volatile int count
public void increment(){//其他线程可见,原子操作count = 5;//非原子操作,其它线程不可见count = count + 1;count++;
}    

synchronized 关键字

锁 Java 对象,锁 Class 对象,锁同步代码块

  • 锁方法上,未获取到 对象锁的其他线程不可以访问该方法
synchronized void method(){}
  • 锁 Classs 对象,加在 static 方法上相当于给 Class 对象加锁,哪怕是不同的 Java对象实例。也需要排队执行
synchronized static void method(){}
  • 锁代码块上,未获得对象锁的线程可以同步执行代码块之外的代码
void method(){Log.i(TAG,"code out before the synchronized");synchronized(this){}
}

synchronized 的优劣势

优势:

  • 如果同步方法中出现了异常,Jvm 也能够为我们自动释放锁,从而避免死锁,不需要开发者手动释放锁

劣势:

  • 必须要等到获取锁对象的线程执行完成,或者出现异常,才能释放锁。不能中途释放锁,不能中断一个正在试图获取锁的线程。
  • 无法获知多个线程竞争锁的时候,获取锁是否成功,不够灵活
  • 每个锁只有单一的条件,不能设置超时等

ReentratLock 悲观锁,可重入锁,公平锁,非公平锁

  • 基本用法
ReentratLock lock = new ReentratLock();
try{lock.lock();....
}finally{locak.unLock();
}
void lock();//获取不到会阻塞
boolean tryLock();//尝试获取锁,成功返回 true
boolean tryLock(3000,TimeUnit.MILLISECONDS);//在一定时间内不断尝试去获取锁
void lockInterruptibly();//可使用Thread.interrupt()打断阻塞状态,退出竞争,让给其他线程
  • 可重入,避免死锁
ReentratLock lock = new ReentratLock();
public void doWork(){try{lock.lock();doWork();//递归调用,使得同一线程多次获取锁}finally{locak.unLock();}
}
  • 公平锁 与 非公平锁

    • 公平锁:所有进入阻塞的线程排队一次均有机会执行
    • 默认非公平锁:允许线程插队,避免每一个线程都进入阻塞,在唤醒,性能高。因为线程可以插队,导致队列中可能会存在线程饿死的情况,一直得不到执行。
  • Condition 条件对象

    • 可以使用 awit-singal 指定唤醒一个(组)线程。相比于 wait-notify 要么全部唤醒,要么只能唤醒一个,更加灵活
    ReentrantLock lock = new ReentrantLock();               
    Condition worker1 = lock.newCondition();                
    Condition worker2 = lock.newCondition();                class Worker1{                                          ....                                                worker1.await();//进入阻塞,等待唤醒                         ....                                                
    }                                                       class Worker2{                                          ....                                                worker2.await();//进入阻塞,等待唤醒                         ....                                                
    }                                                       class Boss{                                             if(...){                                            worker1.signal();//指定唤醒线程1                      }else{                                              worker2.signal();//指定唤醒线程2                      }                                                   
    }                                                       
    

4.线程池

为什么引入线程池?

  • 降低资源消耗 :通过重复利用已创建的线程降低线程创建和销毁造成的开销。
  • 提高相应速度: 当任务到达时,就不需要等待线程的创建就可以立即执行。
  • 提高线程的可管理性:线程属于稀缺资源,如果无限制的创建,不近会消耗系统资源,还会降低系统的稳定性。使用线程池可以进行统一的分配,调优和监控

Java中默认的线程池。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MUy3GsH6-1634264627406)(../../pic/1628176650583.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jdne6lCQ-1634264627407)(../../pic/1628176667371.png)]

JUC包下 Executors 提供的几种线程池

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Xyy2yfT5-1634264627408)(../../pic/image-20211015101745157.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-odV0mdlH-1634264627409)(../../pic/1628176788183.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IovVtSex-1634264627410)(../../pic/1628176879217.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Y0xWSzHF-1634264627410)(../../pic/1628176954923.png)]


http://chatgpt.dhexx.cn/article/puN2HH9N.shtml

相关文章

【安卓开发】安卓网络编程

目录 一、安卓Socket客户端二、安卓Socket客户端优化(小车遥控器拓展)三、Android非UI线程修改空间程序崩溃问题一种新的解决办法:Handler类(倒计时软件) 四、Android网络接收数据并刷新界面(综合练习&…

storm-executor-spout(2)

2121SCSDUSC storm-executor-spout(2) 用一个spout读取Twitter数据。采用拓扑并行化,多个spout从同一个流读取数据的不同部分。如果有多个流要读取,可以在任意组件内(spouts/bolts)访问TopologyContext。…

php读取excel效率,PhpSpreadsheet VS Box\Spout读取excel性能对比

phpspreadsheet版本:1.5.0 spout版本:2.7.3 在同样的环境下,运行代码,spout的在内存使用和时间花费上都占优,在phpspreadsheet读取失败的文档spout依然能正确完成读取。 spout代码 ini_set(memory_limit, 2G); var_dump(memory_get_usage()); var_dump(microtime()); $loa…

KafkaSpout 浅析

最近在使用storm做一个实时计算的项目,Spout需要从 KAFKA 集群中读取数据,为了提高开发效率,直接使用了Storm提供的KAFKA插件。今天抽空看了一下KafkaSpout的源码,记录下心得体会。 KafkaSpout基于kafka.javaapi.consumer.SimpleConsumer实现…

storm trident的多数据流,多spout

storm trident的多数据流,多spout (STORM)[storm, kafka] storm可以使用接收多个spout作为数据源,core storm与trident均可以,本文主要介绍trident的用法。 在trident中设置多个spout的基本思路是先建立多个spout,然后分别创建…

storm学习笔记(二)——Storm组件详解之Tuple、Spout

目录 Tuple元组 结构 生命周期 Spout数据源 结构 开发spout组件 Storm的核心概念包括:Stream、Spout、Bolt、Tuple、Task、Worker、Stream Grouping、Topology Stream是被处理的数据,Spout是数据源,Bolt是处理数据的容器,T…

java 纳秒 格式化_Java日期时间API系列35-----Jdk8中java.time包中的新的日期时间API类应用,微秒和纳秒等更精确的时间格式化和解析。...

通过Java日期时间API系列1-----Jdk7及以前的日期时间类中得知,Java8以前除了java.sql.Timestamp扩充纳秒,其他类最大只精确到毫秒;Java8 time包所有相关类都支持纳秒。下面是示意图: 图中的nano 是 一秒钟包含的纳秒值,0到999999999。毫秒,微秒和纳秒都是通过这个值计算得…

c语言计时程序 纳秒,前端Tips#4 - 用 process.hrtime 获取纳秒级的计时精度

视频讲解 文字讲解 如果去测试代码运行的时长,你会选择哪个时间函数? 一般第一时间想到的函数是 Date.now 或 Date.getTime。 1、先讲结论 之所以这么选,是基于 精度 和 时钟同步 两方面考虑的。 2、知识讲解 首先看一下 Date.now 的缺点 返回…

纳秒时代

1978年在英特尔公司的历史中是很不平凡的一年。这一年它满10岁了,员工数首次超过1万人。这一年,它卖掉了竞争激烈的电子表(digital watch)业务。最重要的是,在这一年6月,它推出了具有跨时代意义的8086芯片。…

linux内核纳秒精度时间,Linux时钟精度:毫秒?微妙?纳秒?

最近被内核时钟精度弄的很是郁闷。具体情况如下: 扫盲:1秒1000毫秒1000000微妙1000000000纳秒 首先:linux有一个很重要的概念——节拍,它的单位是(次/秒)。2.6内核这个值是1000,系统中用一个HZ的宏表征这个值。同时有全…

java 日期 纳秒_java8 ZonedDateTime 日期精度到纳秒

1秒 10E3毫秒 10E6 微妙 10E9 纳秒 使用java8 Instant 内部实际System.currentTimeMillis() 在模型上 可输出纳秒数据 重点是模型 时间戳转日期 public static ZonedDateTime ofInstant(Instant instant, ZoneId zone) { Objects.requireNonNull(instant, "instant&qu…

第九章:NAT(网络地址转换协议)

文章目录 一、NAT1、NAT介绍①公有网络地址②私有网络地址 2、NAT工作原理3、NAT功能 二、NAT的实现方式1、静态转换(static Translation)实验对比 2、动态转换2.1 ACL(访问控制列表)2.2 配置动态NAT实验效果 3、端口多路复用3.1 …

【NAT网络地址转换(私网公网地址、静态NAT、动态NAT、NAPT、Easy IP、NAT Server)】-20211215、20211216

目录 一、NAT产生背景 1.产生背景 2.私网地址、公网地址​ 私网IP地址,既可以一定上缓解ip的不足,在私网里,ip地址可以随意使用。 公网地址,在需要访问公网时,运用网络地址转换NAT技术,可以实现。 二…

什么是私网,公网?

我们常说的内网和外网,通常是相对于防火墙而言的,在防火墙内部叫做内网,反之就是外网。 在一定程度上外网等同于公网,内网等同于私网。公网地址 公网地址是指在因特网上直接可达的地址,如果你有一个公网地址&#xff0…

NAT——公私网地址转换

NAT—网络地址转换 NAT NAT又称为网络地址转换,用于实现私有网络和公有网络之间的转换 私有和公有网络地址 公有网络地址是指互联网上全球唯一的IP地址 私有网络地址是指内部网络或者主机的IP地址 IANA(互联网数字分配机制)规定将下列的IP地…

公网地址和私网地址问题

服务器映射用于将内网服务器的私网地址映射为公网地址,供Internet用户访问。选择“静态映射”类型可以将每一台服务器映射成一个独立的公网IP地址。“服务器负载均衡”类型可以将多台服务器映射成同一个公网地址,Internet用户在访问这个公网地址时&#…

私网地址与Internet地址

一、A、B、C三类地址 可用地址范围备注A类1.0.0.1-126.255.255.254B类128.1.0.1-191.255.255.254C类192.0.1.1-223.255.255.254D类224.0.0.1-239.255.255.254D类为多播地址 说明: 1. 每一个地址都是用网络位主机位组成的。 2. 全0的和全1的网络位和主机位都要去掉…

计算机网络 网络层 私网地址和公网地址及子网划分

公网地址 公有地址分配和管理由Inter NIC(Internet Network Information Center 因特网信息中心)负责。各级ISP使用的公网地址都需要向Inter NIC提出申请,有Inter NIC统一发放,这样就能确保地址块不冲突。 私网地址(不…

为什么百度查到的ip和ipconfig查到的不一样;详解公网Ip和私网ip;详解网络分类ABC;

IP可以分为Public IP 和 Private IP,出现这种规划的原因在于IPv4所能表示的IP太少而电脑太多以至于不够用,然而只有Public IP才能直接连接上网络,所以对于那些公司,学校,政府机构等场所,就可以集中使用私有的IP进行管理…