Processes and Threads

当一个应用的组件启动但是应用没有启动任何其他的组件运行,android就会启动一个新的Linux进程为一个应用开启一个单独的执行线程。默认的同一应用中的所有组件都是运行在同一个进程和主线程中。如果一个应用组件启动并且当这个进程已经存在(因为另外的这个应用的组件已经存在),然后这个组件启动在这个应用的进程中并使用同一个线程执行。但是你可以安排不同的组件在不同的进程中,也可以创建额外的线程在任何进程中。这里讨论怎么样进程和线程工作。

进程

默认的应用中所有的组件都是运行在同一个进程中,大多数应用不能改变这个,但是假如你需要控制哪些组件属于哪些进程,你可以在清单文件中控制。
清单文件的条目中各个组件都支持一个android:process属性这个可以修改组件在应用中的某个进程。你可以设置属性是每个组件都有自己的进程或不分享。你可以设置android:process是不同的应用组件在同一个进程之中,提供这个应用分享的同一个linux用户id和被同一个证书签名。

<application>标签也支持一个andorid:process属性,去设置默认的所有应用组件。
android也许决定关闭一个进程在某个时候,当内存低的时候或者其他的进程更直接的服务用户。应用组件运行在一个进程中会经常被销毁。当需要工作的时候,一个进程被重启的启动工作。
当决定进程被销毁后,android系统会权衡那个比较相对重要对用户。比如,他更容易关闭托管的activity。这个决定是否关闭进程,因此,取决于组件的运行状态。这个关闭的规则在下面讨论。

进程的生命周期

android系统会试着坚持尽可能长,但是最终需要移除老的进程来释放内容为新的应用或更重要的进程。觉得那个进程留下哪个被销毁,系统会放置很重要的层次里基于运行中的组件的状态。进程低重要程度的被淘汰,然后下一个不太重要的等等,这样是回收资源必须的。
1.前端进程:
一个用户操作的进程,这个进程被认为是前端的符合以下条件:
*一个activity用户正在交互(在调用onResume方法后)
*service绑定在一个用户的交互的activity上
*service正在前端运行,服务调用了startForeground().
*service正在执行一个生命周期(onCreate,onStart,onDestroy)
*broadcaseReceiver执行onReceive方法。
一般只有一个或几个前端的工作。被销毁只能作为最后的手段,假如内存低到他们不能继续运行。一般设备已经达到了内存分页的状态,以至于去杀掉前端的进程保持用户界面的响应。
2.可见进程
一个进程没有任何的前端操作组件,但是仍然影响用户看到的。一个进程可以被认为是可见的。
*一个activity不是在前端组件,但是他仍然可见,当这个时候,举个例子假如前端开启一个dialog,activity就会在背后。
*一个service绑定在一个可见的activity。
一个可见的进程可以认为非常的重要并且不会被销毁保证全部前端进程正在运行时。
3.服务进程
一个进程是一个服务被startServie方法启动并且不再两个更高的类。虽然服务进程不是直接的被用户看到,他们会做一些事用户会感觉的到(比如播放音乐或者从网络中下载数据),所以系统需要保持运行除非他们没有足够的内存当前端和可见的进程。
4.后台进程
一个进程只有一个activity当前不可见(onStop方法之后),这些进程不会影响用户的体验。通常这些许多后台进程运行,他们会保持一个LRU队列来确定一个activity最少最近的时候被销毁。假如一个activity实现了生命周期方法保存当前的状态杀掉进程后不会影响用户体验,因为当用户返回activity时activity已经存储了可见的状态。
5.空进程
一个进程不激活任何一个应用组件,这个唯一的理由是保存这个进程活着为了缓存目的,提高下次启动时间。这个时候系统会销毁这些进程为平衡这个系统的资源在进程缓和内存缓存。

android区分进程的最高等级,是基于当前活动的组件激活组件的活跃程度。比如一个进程持有一个服务和一个可见activity,这个进程的等级就是可见进程,不是服务进程。

另外,一个进程的等级会因为另外的进程需要依赖它而增加,一个进程可以服务另外一个排名低于他的进程。比如一个通信录提供进程A中服务一个进程B,或者这个服务在进程A被限制在一个组件的进程中,进程A至少比进程B更重要。
因为一个进程可以运行一个服务高于一个后台进程,一个activity初始很长时间开始一个服务操作,比如一个简单的创建一个线程,特别是一些创建简单的工作线程。比如一个activity上传一个图片到web站你会启动一个服务执行上传所有上传可以继续在后台当即使用户离开activity。使用服务可以保证至少是一个服务进程,不管activity发生什么。这一原因broadcastReceiver应该使用一个service而不是简单的使用线程操作。

线程

当一个应用启动后,系统会创建一个主线程。这个线程十分的重要因为它分发所有的事件给合适的用户界面包括绘画事件。这个线程在应用中和组件交互。所以这个主线程被称为UI线程。
系统不会单独的创建一个线程为单个组件。所有的组件都是运行在同一个被初始化的进程UI线程中,并且系统会调用每个组件的分发从线程中。所以,这个方法回应系统回调(比如onKeyDown())会回复应用的动作或者生命周期的回调函数都在进程的UI线程中。
举个例子,当用户点击一个按钮再屏幕上,你的应用UI线程会发送一个点击的事件给组件,反过来设置按下的状态并发送一个无效的请求在事件队列中。这个ui线程会分发请求并通知组件刷新自己。
当你的应用执行密集型工作在响应用户交互,这个单线程可能会导致执行效率低除非你实现你的应用很适当。特别是假如每个事件发生在UI线程中,执行很长时间的操作像网络访问,数据库查询会阻塞这个UI。当线程被阻塞,没有时间可以被分发,包括绘制事件。从用户的角度看,这个应用看上去会挂。更糟的是假如U线程被阻塞5秒钟就会提示用户ANR对话框。用户会很不高兴并且卸载它。

再者android的UI线程不是线程安全的。所以你不能控制UI在另外一个工作线程中,你必须所有的操作都在你的UI线程中控制。因此有两个规则:
1.不能阻塞线程
2.不能通过andorid UI toolkit从外部访问UI 线程。

工作线程

因为是单线程模式,这个很重要对于你的应用的UI,你不能阻塞UI线程。假如你的操作执行不是在瞬间,你应该明确你做的这些在一个独立的线程里。

比如下面的一个代码一个点击下载图片从一个线程展现ImageView。首先这个看上去很工作很正确,因为他创建的一个新的线程去执行网络操作,但是他违反了单个线程模式的第二个规则:不能通过android UI toolkit访问外部UI线程。这个简单修改在工作线程中代替你UI线程。这个会导致意想不到的行为,很难很耗时追踪。
为了修复这个问题,andorid提供了UI线程从其他线程进程访问。这里例句了方法:

1.      Activity.runOnUiThread(Runable);

2.      View.post(Runable)

3.      View.post(Runable,long)

比如,你可能需要使用View.post(Runable)方法。
现在实现一个线程安全:网络的操作在一个独立的线程里做当ImageView被操作在UI的线程里。

但是随着操作的复杂,这种代码复杂难维护。为了操作更复杂的交互和线程工作,你而已考虑使用Handler在工作的线程中,在过程中发送消息给UI线程。也许最好解决的方法是继承AsyncTask类,这个简单的执行一个工作线程任务可以和 UI交互。

使用AsyncTask

asyncTask允许执行异步的工作在你的界面中。这个执行不会阻塞操作在工作线程中并且发布结果到UI进程,不需要你处理线程和handler。
使用这个你必须继承asyncTask并实现一个doInbackground回调方法,这个是运行在一个后台的线程池中。更新你的UI,你应该在onpostexcute方法里,这个传递一个标记从ddoinBackground并运行在UI的主线程中,所以你可以线程安全更新你的UI。你可以运行这个任务使用execute在UI线程中。
现在UI是安全的并且代码也更简单,因为分离工作和一个UI工作部分。
你应该阅读asyncTask引用为一个全面理解怎么样使用这个类,但是这里快速的概括一下怎么样工作的。
1.你可以指定参数类型,进度值,最后的task值,用的范型。
2.方法doinBackground自动执行一个线程工作。
3.onPreExecute(),onPostExecute(),和onProgressUpdate被UI线程调用。
4.返回值被doinBackground发送给onPostExecute().
5.你可以调用publishProgress()在任何时候再doinBackground执行onProgressUpdate在UI线程中。
6.你可以取消任务在任何时候,从任何的线程中。
注意:
另外一个问题是你也许会遭遇当使用一个工作线程因为意想不到的事重启你的activity,比如运行时配置(像用户旋转屏幕),这个可能会销毁你的工作线程。想看看你怎么保持任务重启的时候怎么取消一个任务当activity被销毁,看源码shelves应用。

线程安全的方法

这些问题,你这个方法你使用的可以被调用超过一个线程,因此你必须写一个线程安全。
这个最适合用的方法用远程的像bound service。当你调用一个方法实现一个IBinder源在同一个进程中IBinder运行,这个方法被执行在一个线程中从线程池中这个系统支持一个同一个进程IBinder(它不执行在UI线程)。比如,服务的onBind()方法被调用在UI线程的进程中,这个方法返回一个对象onBind返回(比如,一个子类实现RPC方法)可以调用在其他的线程在线程池中。因为一个服务可以有多个客户,多个线程池应答同一个IBinder方法在同一个时间。IBinder方法必须,因此这个方法的实现是线程安全的。
相同的,一个内容提供者可以接收数据的请求来自其他的进程。虽然,Content Resolver和Content Provider类隐藏了进程间如何管理,ContentProvder方法回应一个请求的方法是query(),insert(),delete(),update(),和getType()这些都可以调用从一个线程在内容提供者的线程中。因为这些方法可以被无数个线程同时调用在同一时间,他们也必须实现线程安全。

进程间通信

android提供了一个机制用于进程间通信远程的请求,在一个方法被一个activity或另一个组件调用,但是远程执行(在另个进程中),和任何返回的结果调用者。这个需要分解方法调用和数据操作系统可以理解的水平,传送他从本地进程到远程的进程地址空间,然后重新装配重新定制。返回的值传递到返回的方向。返回的值传递到相反的方向。android提供了所有执行IPC事务,所以你可以聚焦在定义的实现RPC程序接口。

使用优化算法,以优化VMD算法的惩罚因子惩罚因子 (α) 和分解层数 (K)。 1、将量子粒子群优化(QPSO)算法与变分模态分解(VMD)算法结合 VMD算法背景: VMD算法是一种自适应信号分解算法,主要用于分解信号为不同频率带宽的模态。 VMD的关键参数包括: 惩罚因子 α:控制带宽的限制。 分解层数 K:决定分解出的模态数。 QPSO算法背景: 量子粒子群优化(QPSO)是一种基于粒子群优化(PSO)的一种改进算法,通过量子行为模型增强全局搜索能力。 QPSO通过粒子的量子行为使其在搜索空间中不受位置限制,从而提高算法的收敛速度与全局优化能力。 任务: 使用QPSO优化VMD中的惩罚因子 α 和分解层数 K,以获得信号分解的最佳效果。 计划: 定义适应度函数:适应度函数根据VMD分解的效果来定义,通常使用重构信号的误差(例如均方误差、交叉熵等)来衡量分解的质量。 初始化QPSO粒子:定义粒子的位置和速度,表示 α 和 K 两个参数。初始化时需要在一个合理的范围内为每个粒子分配初始位置。 执行VMD分解:对每一组 α 和 K 参数,运行VMD算法分解信号。 更新QPSO粒子:使用QPSO算法更新粒子的状态,根据适应度函数调整粒子的搜索方向和位置。 迭代求解:重复QPSO的粒子更新步骤,直到满足终止条件(如适应度函数达到设定阈值,或最大迭代次数)。 输出优化结果:最终,QPSO算法会返回一个优化的 α 和 K,从而使VMD分解效果最佳。 2、将极光粒子(PLO)算法与变分模态分解(VMD)算法结合 PLO的优点与适用性 强大的全局搜索能力:PLO通过模拟极光粒子的运动,能够更高效地探索复杂的多峰优化问题,避免陷入局部最优。 鲁棒性强:PLO在面对高维、多模态问题时有较好的适应性,因此适合海上风电时间序列这种非线性、多噪声的数据。 应用场景:PLO适合用于优化VMD参数(α 和 K),并将其用于风电时间序列的预测任务。 进一步优化的建议 a. 实现更细致的PLO更新策略,优化极光粒子的运动模型。 b. 将PLO优化后的VMD应用于真实的海上风电数据,结合LSTM或XGBoost等模型进行风电功率预测。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值