android并发
‘壹’ android推送xmpp和mqtt单台服务器支持连接多少,并发多少,求两种协议比较,有测试过的吗
根据实地观察,单台mqtt服务如果并发达到5w以上,就经常出故障;在2w左右内网访问服务器就比较卡了。
注:配置是4核 16G内存,虚机。配置有点差。对CPU的消耗比较高,内存基本没啥消耗,所以建议把CPU整好点。
‘贰’ androidlist并发导致重复数据
1、首先,通过循环进行删除。
2、其次,通过HashSet删除。
3、最后,定义一个方法,调用即可。
‘叁’ 每个Android 都应必须了解的多线程知识点~
进程是系统调度和资源分配的一个独立单位。
在Android中,一个应用程序就是一个独立的集成,应用运行在一个独立的环境中,可以避免其他应用程序/进程的干扰。当我们启动一个应用程序时,系统就会创建一个进程(该进程是从Zygote中fork出来的,有独立的ID),接着为这个进程创建一个主线程,然后就可以运行MainActivity了,应用程序的组件默认都是运行在其进程中。开发者可以通过设置应用的组件的运行进程,在清单文件中给组件设置:android:process = "进程名";可以达到让组件运行在不同进程中的目的。让组件运行在不同的进程中,既有好处,也有坏处。我们依次的说明下。
好处:每一个应用程序(也就是每一个进程)都会有一个内存预算,所有运行在这个进程中的程序使用的总内存不能超过这个值,让组件运行不同的进程中,可以让主进程可以拥有更多的空间资源。当我们的应用程序比较大,需要的内存资源比较多时(也就是用户会抱怨应用经常出现OutOfMemory时),可以考虑使用多进程。
坏处:每个进程都会有自己的虚拟机实例,因此让在进程间共享一些数据变得相对困难,需要采用进程间的通信来实现数据的共享。
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。
在Android中,线程会有那么几种状态:创建、就绪、运行、阻塞、结束。当应用程序有组件在运行时,UI线程是处于运行状态的。默认情况下,应用的所有组件的操作都是在UI线程里完成的,包括响应用户的操作(触摸,点击等),组件生命周期方法的调用,UI的更新等。因此如果UI线程处理阻塞状态时(在线程里做一些耗时的操作,如网络连接等),就会不能响应各种操作,如果阻塞时间达到5秒,就会让程序处于ANR(application not response)状态。
1.线程作用
减少程序在并发执行时所付出的时空开销,提高操作系统的并发性能。
2.线程分类
守护线程、非守护线程(用户线程)
2.1 守护线程
定义:守护用户线程的线程,即在程序运行时为其他线程提供一种通用服务
常见:如垃圾回收线程
设置方式:thread.setDaemon(true);//设置该线程为守护线程
2.2 非守护线程(用户线程)
主线程 & 子线程。
2.2.1 主线程(UI线程)
定义:Android系统在程序启动时会自动启动一条主线程
作用:处理四大组件与用户进行交互的事情(如UI、界面交互相关)
因为用户随时会与界面发生交互,因此主线程任何时候都必须保持很高的响应速度,所以主线程不允许进行耗时操作,否则会出现ANR。
2.2.2 子线程(工作线程)
定义:手动创建的线程
作用:耗时的操作(网络请求、I/O操作等)
2.3 守护线程与非守护线程的区别和联系
区别:虚拟机是否已退出,即
a. 当所有用户线程结束时,因为没有守护的必要,所以守护线程也会终止,虚拟机也同样退出
b. 反过来,只要任何用户线程还在运行,守护线程就不会终止,虚拟机就不会退出
3.线程优先级
3.1 表示
线程优先级分为10个级别,分别用Thread类常量表示。
3.2 设置
通过方法setPriority(int grade)进行优先级设置,默认线程优先级是5,即 Thread.NORM_PRIORITY。
4.线程状态
创建状态:当用 new 操作符创建一个线程的时候
就绪状态:调用 start 方法,处于就绪状态的线程并不一定马上就会执行 run 方法,还需要等待CPU的调度
运行状态:CPU 开始调度线程,并开始执行 run 方法
阻塞(挂起)状态:线程的执行过程中由于一些原因进入阻塞状态,比如:调用 sleep/wait 方法、尝试去得到一个锁等
结束(消亡)状态:run 方法执行完 或者 执行过程中遇到了一个异常
(1)start()和run()的区别
通过调用Thread类的start()方法来启动一个线程,这时此线程是处于就绪状态,并没有运行。调用Thread类调用run()方法来完成其运行操作的,方法run()称为线程体,它包含了要执行的这个线程的内容,run()运行结束,此线程终止,然后CPU再调度其它线程。
(2)sleep()、wait()、yield()的区别
sleep()方法属于Thread类,wait()方法属于Object类。
调用sleep()方法,线程不会释放对象锁,只是暂停执行指定的时间,会自动恢复运行状态;调用wait()方法,线程会放弃对象锁,进入等待此对象的等待锁定池,不调用notify()方法,线程永远处于就绪(挂起)状态。
yield()直接由运行状态跳回就绪状态,表示退让线程,让出CPU,让CPU调度器重新调度。礼让可能成功,也可能不成功,也就是说,回到调度器和其他线程进行公平竞争。
1.Android线程的原则
(1)为什么不能再主线程中做耗时操作
防止ANR, 不能在UI主线程中做耗时的操作,因此我们可以把耗时的操作放在另一个工作线程中去做。操作完成后,再通知UI主线程做出相应的响应。这就需要掌握线程间通信的方式了。 在Android中提供了两种线程间的通信方式:一种是AsyncTask机制,另一种是Handler机制。
(2)为什么不能在非UI线程中更新UI 因为Android的UI线程是非线程安全的,应用更新UI,是调用invalidate()方法来实现界面的重绘,而invalidate()方法是非线程安全的,也就是说当我们在非UI线程来更新UI时,可能会有其他的线程或UI线程也在更新UI,这就会导致界面更新的不同步。因此我们不能在非UI主线程中做更新UI的操作。
2.Android实现多线程的几种方式
3.为何需要多线程
多线程的本质就是异步处理,直观一点说就是不要让用户感觉到“很卡”。
4.多线程机制的核心是啥
多线程核心机制是Handler
推荐Handler讲解视频: 面试总被问到Handler?带你从源码的角度解读Handler核心机制
根据上方提到的 多进程、多线程、Handler 问题,我整理了一套 Binder与Handler 机制解析的学习文档,提供给大家进行学习参考,有需要的可以 点击这里直接获取!!! 里面记录许多Android 相关学习知识点。
‘肆’ android多核,多线程该如何用
在程序开发的实践当中,为了让程序表现得更加流畅,我们肯定会需要使用到多线程来提升程序的并发执行性能。但是编写多线程并发的代码一直以来都是一个相对棘手的问题,所以想要获得更佳的程序性能,我们非常有必要掌握多线程并发编程的基础技能。
众所周知,Android 程序的大多数代码操作都必须执行在主线程,例如系统事件(例如设备屏幕发生旋转),输入事件(例如用户点击滑动等),程序回调服务,UI 绘制以及闹钟事件等等。那么我们在上述事件或者方法中插入的代码也将执行在主线程。
一旦我们在主线程里面添加了操作复杂的代码,这些代码就很可能阻碍主线程去响应点击/滑动事件,阻碍主线程的 UI 绘制等等。我们知道,为了让屏幕的刷新帧率达到 60fps,我们需要确保 16ms 内完成单次刷新的操作。一旦我们在主线程里面执行的任务过于繁重就可能导致接收到刷新信号的时候因为资源被占用而无法完成这次刷新操作,这样就会产生掉帧的现象,刷新帧率自然也就跟着下降了(一旦刷新帧率降到 20fps 左右,用户就可以明显感知到卡顿不流畅了)。
为了避免上面提到的掉帧问题,我们需要使用多线程的技术方案,把那些操作复杂的任务移动到其他线程当中执行,这样就不容易阻塞主线程的操作,也就减小了出现掉帧的可能性。
那么问题来了,为主线程减轻负的多线程方案有哪些呢?这些方案分别适合在什么场景下使用?Android 系统为我们提供了若干组工具类来帮助解决这个问题。
AsyncTask: 为 UI 线程与工作线程之间进行快速的切换提供一种简单便捷的机制。适用于当下立即需要启动,但是异步执行的生命周期短暂的使用场景。
HandlerThread: 为某些回调方法或者等待某些任务的执行设置一个专属的线程,并提供线程任务的调度机制。
ThreadPool: 把任务分解成不同的单元,分发到各个不同的线程上,进行同时并发处理。
IntentService: 适合于执行由 UI 触发的后台 Service 任务,并可以把后台任务执行的情况通过一定的机制反馈给 UI。
了解这些系统提供的多线程工具类分别适合在什么场景下,可以帮助我们选择合适的解决方案,避免出现不可预期的麻烦。虽然使用多线程可以提高程序的并发量,但是我们需要特别注意因为引入多线程而可能伴随而来的内存问题。举个例子,在 Activity 内部定义的一个 AsyncTask,它属于一个内部类,该类本身和外面的 Activity 是有引用关系的,如果 Activity 要销毁的时候,AsyncTask 还仍然在运行,这会导致 Activity 没有办法完全释放,从而引发内存泄漏。所以说,多线程是提升程序性能的有效手段之一,但是使用多线程却需要十分谨慎小心,如果不了解背后的执行机制以及使用的注意事项,很可能引起严重的问题。