导航:首页 > 操作系统 > android并发执行

android并发执行

发布时间:2022-12-09 00:24:42

A. android IPC机制

IPC是指两个进程之间进行数据交互的过程,即:跨进程通信。
进程是一个执行单,在移动设备上指一个程序或者一个应用。一个进程可以有多个线程,也可以只有一个线程,即主线程。在Android里边,主线程也叫作UI线程,要是在主线程执行大量耗时任务,就会造成界面无法响应,ANR问题,解决这类问题,把耗时操作放在子线程就好。
在Android中,最有特色的进程间通信就是Binder,Binder轻松的实现了进程间的通信。

给四大组件 Activity、Service、Receiver、ContentProvider 在AndroidMenifeist中指定 android:process 属性,可以指定其运行的进程。
: 开头的线程是当前应用的私有进程,其它应用不可以和它跑在同一个进程中,而不以 : 开头的属于全局进程,其他应用通过ShareUID方式可以和它跑在一个进程中。

Android为了每一个应用(进程)都分配了独立的虚拟机,不同的虚拟机在内存分配上有不同的地址空间。
多进程会造成如下几个反面方面的问题:

为了解决这些问题,系统提供了跨进程通信方法,虽然不能直接共享内存,但是可以实现数据共享。Intent来传递数据,共享文件,基于Binder的Messenger,ContentProvider,AIDL和Socket。

当我们需要通过Intent和Binder传输数据,或者我们需要把对象持久化到存储设备上,再或者通过网络传输给其它客户端时,Serializable和Parcelable接口可以完成对象的序列化过程。

Serialzable是java提供的序列化接口,是一个空接口,为对象同序列化和反序列化操作。
想让一个类对象实现序列化,只需要这个类实现Serialzable接口,并声明一个serialVersionUID即可,serialVersionUID可以声明成1L或者IDE根据当前类接口自动生成它的hash值。
没有serialVersionUID不影响序列化,但是可能会影响反序列化。序列化时,系统当前类的serialVersionUID写入序列化文件中,当反序列化时,回去检测文件中的serialVersionUID,看它是否和当前类的serialVersionUID一致,如果不一致,无法完成反序列化。

Seriallizable用起来简单但是开销大,序列化和反序列过程需要大量的I/O操作,而Parcelable是Android序列化方式,更适合Android平台,效率更高。Parcelable主要用于内存序列化上,而Seriallizable更适用于序列化到本地存储设备,或者将对象序列化后通过网络传输到别的客户端。

Activity、Service、Receiver都支持在 Intent中传递Bundle数据,Bundle实现了Pareclable接口,所以它可以方便地在不同进程间传输。

Android基于Linux,使得其并发读写文件可以没有限制的进行,两个进程可以通过读写一个文件来交换数据。共享数据对文件格式没有要求,双反约定就行。使用文件共享很有可能出问题。
SharedPreferences是个特例,虽然也是属于文件的一种,但是由于系统对它的读写有一定的缓存策略,即在内存中会有一份SharedPreferences文件的缓存,因此在多进程模式下,系统对他的读写变得不可靠,高并发的时候,很大可能会丢失数据。

Messenger可以在不同的进程中传递Message对象,在Message中存入我们需要传递的数据,就可以实现数据的跨进程传递。它是一种轻量级的IPC方案,底层实现是AIDL。
Messenger对AIDL做了封装,使得我们可以更便捷的实现跨进程通信,它一次只处理一个请求,在服务端不用考虑线程同步问题,在服务端不存在并发执行的情形。实现一个Messenger有如下几个步骤:

在服务端创建一个Service,同时创建一个Handler,并通过它来创建一个Messenger对象,然后再Service的onBind中返回这个Messenger对象底层Binder即可。

绑定服务端Service,绑定成功后用服务端返回的IBinder对象创建一个Messenger。通过这个对象就可以向服务端发消息了。如果需要服务端回应客户端,就需要和服务端一样,创建一个Handler,并通过它来创建一个Messenger对象,然后把这个Messenger对象通过Message的replyTo参数传给服务端,服务端可以通过这个replyTo参数回应客户端。

首先要创建一个Service用来监听客户端的连接请求,然后创建一个AIDL文件,将暴露给客户端的接口在这个AIDL文件中声明,最后在Service中实现AIDL接口即可。

绑定服务端的Service,将服务端返回的Binder对象转成AIDL接口所属的类型,接着就可可以范文AIDL里边的方法了。

在AIDL文件中,并不是所有的额数据类型都是可以使用的。

以上6种数据就是AIDL所支持的所有类型,其中自定义的Parecelable对象和AIDL对象必须显示的import,不管是否和当前的AIDL文件位于同一个包。
AIDL文件中用到了自定义的Parcelable对象,必须新建一个同名的AIDL文件,在其中声明它为parcelable类型。
AIDL中除了基础数据类型,其它类型参数都需要标上方向:in、out、inout,in是输入型参数,out是输出型参数,inout是输入输出型参数。

上面是远程服务端示例,AIDL方法在服务端的Binder线程池中执行,因此各个客户端同时连接的时候,会存在多个线程同时访问的情形,所以要在AIDL中处理线程同步,这个CopyOnWriteArrayList支持并发的读写。
AIDL所支持的是一个抽象的List,只是一个接口,因此虽然服务端返回的是CopyOnWriteArrayList,当时Binder会按照List规范去范文数据并最终形成一个ArrayList传递给客户端。

ServiceConnection 的回调方法在UI线程中运行,服务端的方法有可能很久才能执行完毕,需要考虑ANR的问题。
服务的方法本省就运行再Binder线程池中,本身可以执行大量耗时操作,不要去服务端方法中开县城去进行异步任务。

客户端

服务端

RemoteCallbackList是系统提供专门用于删除跨进程listener的,它的内部有一个Map结构,用来保存所有的AIDL回调,这个Map的key就是Binder类型,value是CallBack类型。
客户端解注册的时候,我们只需要遍历服务端所有的listener,找出那个和接注册listener具有相同的Binder对象的服务端listener并把它删除即可。
RemoteCallbackList的beginBroadcast和finishBroadcast必须配对使用。

ContentProvider是Android专门提供不同应用间进行数据共享的方式。底层实现一样是Binder。
系统预置了许多ContentProvider,比如通讯录,日程信息表,只需要通过ContentResolver的query、update、insert、delete方法即可。

B. android开发需要注意什么

1、不要排斥新技术和新工具。
Android Studio 1.0 之后的版本,基本已经稳定到可以支持正常的工作开发的程度了。单纯就书写效率而言,Android Studio 带来的好处绝对大于它和Gradle的学习成本。JetBrains的IDE,用过都说好。
还有就是适当的提升targetSdkVersion到新版本。
2、代码设计方面的问题,大部分都能在Android系统源码里找到解决方案。
当你想设计一个新模块,或者实现一个新ui组件的时候,应该采用哪些设计模式、应该以哪种形式给外界提供接口之类的问题,大部分都可以参考Android系统的源码,找到实现方式。Google为安卓程序员提供了一座现成的宝库。
3、理解Android和Java内存管理方式,至少要理解垃圾回收和Java的引用。
就好比学OC就要先理解黄金法则一样,而java的内存管理,其实比OC要好理解多了。
这可能会帮助你大大减少程序异步操作产生的空指针崩溃。也会帮助你理解为什么滥用单例模式会导致内存的臃肿。还会帮助你养成不用“+”去连接超大字符串的好习惯。
4、ContentProvider并不是只有在跨进程共享数据的才有用,把数据库表映射到一个独立的uri是Google鼓励的实现方式。
从设计上讲,用uri(统一资源标识符)去描述数据,肯定比sql语句要理想。
从效果上讲,用CursorLoader读取数据是让iOS程序员都羡慕不已的事情,作为android程序员,何苦不用呢。
5、理解Activity任务栈。
非Activity的Context对象如果直接启动Activity会报错,这只是一个表面现象,真正起作用的其实是Activity任务栈机制。
理解Activity任务栈机制以及Activity的各种启动方式,会帮助解决大部分页面关系错乱问题,以及应用互相掉起、任务栏进入应用、后台弹窗引起的各种问题。
6、对于一些奇葩的第三方ROM,调用其非主流api的时候,可以使用反射。
在适配一些第三方ROM的的时候,调用一些在开发环境中没有,但在运行环境中有的方法时,可以使用反射。比方说,华为双卡手机可能会提供获取第二块SIM卡信息的api,如果直接调用,在开发环境可能无法通过正常编译,用反射就没问题。这属于不得已而用反射的一种情况。
7、SQLite的锁,是数据库级别的锁,也就是说同一个数据库的写操作无法并发执行。
所以,在数据库设计的时候,如果表太多,尽量将没有关联的表拆到多个数据库文件中。
8、Bitmap的内存占用问题。
这是一个困扰2.X时代android程序员的问题。
2.X时代Bitmap对象虽然存储在堆内存中,但是用了一个byte数组存储其像素信息。通过计数器来记录该像素信息被引用的个数。有人认为这个byte数组在native堆中,但事实上它也在堆中。
只有在使用者调用recycle()后,Bitmap对象才会释放像素信息,才会在失去引用后,被垃圾回收机制销毁。再加上DVM的heap size有严格的阀值,所以在使用大量图片资源的时候,及其容易发生OOM。
解决办法一般都是,用一个哈希表存储Bitmap对象的软引用,作为内存缓存,并在适当时机掉用其recycle()。
3.0以上版本Bitmap对象可以通过垃圾回收机制完全销毁,理论上不用再调用recycle()。

C. android游戏是怎么处理高并发的

现在后台一般用C++或者golang来写,golang专门做高并发后台的

D. android怎么提高线程的优先级

线程调度 计算机通常只有一个CPU,在任意时刻只能执行一条机器指令,每个线程只有获得CPU的使用权才能执行指令.所谓多线程的并发运行,其实是指从宏观上看,各个线程轮流获得CPU的使用权,分别执行各自的任务.在运行池中,会有多个处于就绪状态的线程在等待CPU,JAVA虚拟机的一项任务就是负责线程的调度,线程调度是指按照特定机制为多个线程分配CPU的使用权. 有两种调度模型:分时调度模型和抢占式调度模型。 分时调度模型是指让所有的线程轮流获得cpu的使用权,并且平均分配每个线程占用的CPU的时间片这个也比较好理解。 java虚拟机采用抢占式调度模型,是指优先让可运行池中优先级高的线程占用CPU,如果可运行池中的线程优先级相同,那么就随机选择一个线程,使其占用CPU。处于运行状态的线程会一直运行,直至它不得不放弃CPU。 一个线程会因为以下原因而放弃CPU。 1 java虚拟机让当前线程暂时放弃CPU,转到就绪状态,使其它线程或者运行机会。 2 当前线程因为某些原因而进入阻塞状态 3 线程结束运行 需要注意的是,线程的调度不是跨平台的,它 不仅仅取决于java虚拟机,还依赖于操作系统。在某些操作系统中,只要运行中的线程没有遇到阻塞,就不会放弃CPU;在某些操作系统中,即使线程没有遇到阻塞,也会运行一段时间后放弃CPU,给其它线程运行的机会。 java的线程调度是不分时的,同时启动多个线程后,不能保证各个线程轮流获得均等的CPU时间片。 如果希望明确地让一个线程给另外一个线程运行的机会,可以采取以下办法之一。 调整各个线程的优先级 让处于运行状态的线程调用Thread.sleep()方法 让处于运行状态的线程调用Thread.yield()方法 让处于运行状态的线程调用另一个线程的join()方法

E. 《Android并发开发》pdf下载在线阅读全文,求百度网盘云资源

《Android并发开发》网络网盘pdf最新全集下载:
链接: https://pan..com/s/13Z7F2SE1l1W-V_AefPdFaA

?pwd=kdpe 提取码: kdpe
简介:本书共8章,第1章介绍了一个非典型的并发模型,以后文的阐释做好铺垫。第2章和第3章分别介绍了Java并发和Android应用程序模型,主要介绍Java线程、同步、并发包、生命周期和组件、Android进程等基本概念。第4章介绍AsyncTask和Loader。第5—7章是本书的核心内容,深入探讨Android操作系统的细节,如Looper/Handler、Service、Binder、定时任务等。第8章介绍并发工具,如静态分析、注解、断言等。

本书适合有一定Android开发经验的读者参考。如果你是一名新手,建议你在掌握相关入门知识的基础上阅读本书,以达到更好的学习效果。本书给出多段代码,旨在让读者亲自实践后更好地掌握Android并发开发的相关内容。

F. Android:在代码中我start了一个Thread后,这个线程和原线程并发还是并行

并行、、、、新线程跟原(UI,也叫主线程)同时运行。

G. Android进程与线程区别

所以下来特地去查了以下资料,先说说线程:
(1)在Android APP中,只允许有一个主线程,进行UI的渲染等等,但是不能进行耗时操作(网络交互等等),否则会造成ANR,就是线程阻塞卡死,未响应。
(2)除了主线程之外,耗时操作都应该规范到子线程中,线程之间会有相应的通信方式,但相互独立。
(3)然后看了一下所查资料:
线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。线程比进程更小,基本上不拥有系统资源,故对它的调度所用资源小,能更高效的提高系统内多个程序间并发执行的。 嗯,从大的说就是这样。
在平时的Android开发过程中,基本上都会用到线程handler,thread等等,具体的实现方法我就不在这里写了。

进程:
根据所查资料:是一个具有独立功能的程序关于某个数据集合的一次运行活动。进程是系统进行资源分配和调度的一个独立单位。可以申请和拥有系统资源,是一个动态的概念,是一个活动的实体,是一个“执行中的程序”。不只是程序的代码,还包括当前的活动。
这应该是一个比较大的概念,存在于一个系统中,与线程的区别是:

1、子进程和父进程有不同的代码和数据空间,而多个线程则共享数据空间,每个线程有自己的执行堆栈和程序计数器为其执行上下文。
2、进程间相互独立,同一进程的各线程间共享。某进程内的线程在其它进程不可见。

3、进程间通信IPC,线程间可以直接读写进程数据段(如全局变量)来进行通信——需要进程同步和互斥手段的辅助,以保证数据的一致性。

4、线程上下文切换比进程上下文切换要快得多。

H. android开发中怎样解决多用户并发问题

既然是多用户,那么用户数据应该是分开的,要不就体现不了多用户的机制体系了,用户下的数据应该是私有的,除非用户提供共享并且系统支持共享才可以。对于Android,即Linux系统来说,一个用户即一个文件目录,用户目录之间的互访是受权限控制的,在没有指定权限的情况下,用户间是不能有互相控制的能力的,除非用户获取了系统权限,即我们常说的root权限。在系统内存储,如果获取了root权限,把文件写到系统目录下会是一种方式,root权限不容易获取并存在安全隐患,不推荐这么做。可以绕个思路,内存储不行但还有外置存储(如SD卡),这个是多用户公用的,可以把相关数据放在外置存储器上,达到共享的目的。可以做个参考。

I. Android 开发中,有哪些坑需要注意

1. 为Activity声明系统配置变更事件
系统配置变更事件是指转屏,区域语言发生变化,屏幕尺寸发生变化等等,如果Activity没有声明处理这些事件,发生事件时,系统会把Activity杀掉然后重启,并尝试恢复状态,Activity有机会通过onSaveInstanceState()保存一些基本数据到Bundle中,然后此Bundle会在Activity的onCreate()中传递过去。虽然这貌似正常,但是这会引发问题,因为很多其他的东西比如Dialog等是要依赖于具体Activity实例的。所以这种系统默认行为通常都不是我们想要的。
为了避免这些系统默认行为,就需要为Activity声明这些配置,如下二个是每个Activity必须声明的:
<activity android:configChanges="orientation|keyboardHidden">
几乎所有的Activity都要声明如上,为什么Android不把它们变成Default的呢?
2. 尽量使用Android的API
这好像是废话,在Android上面开发不用Android API用什么?因为Android几乎支持Java SE所有的API,所以有很多地方Android API与Java SE的API会有重复的地方,比如说对于文件的操作最好使用Android里面Context封装的API,而不要直接使用File对象:
Context.openFileOutput(String); // no File file = new File(String)
原因就是API里面会考虑到Android平台本身的特性;再如,少用Thread,而多使用AsyncTask等。
3. 要考虑到Activity和进程被杀掉的情况
如了通常情况退出Activity外,还有Activity因其他原因被杀的情况,比如系统内存过低,系统配置变更,有异常等等,要考虑和测试这种情况,特别是Activity处理重要的数据时,做好的数据的保存。
4. 小心多语言
有些语言真的很啰嗦,中文或英文很简短就能表达的事情到了其他语言就变的死长死长的,所以如果是wrap_content就可能把其他控制挤出可视范围; 如果是指定长度就可能显示不全。也要注意特殊语言比如那些从右向左读的语言。
5. 不要用四大组件去实现接口
一是组件的对象都比较大,实现接口比较浪费,而且让代码更不易读和理解; 另外更重要的是导致多方引用,可能会引发内存泄露。
6. 用getApplication()来取Context当参数
对于需要使用Context对象作为参数的函数,要使用getApplication()获取Context对象当参数,而不要使用this,除非你需要特定的组件实例!getApplication()返回的Context是属于Application的,它会在整个应用的生命周期内存在,远大于某个组件的生命周期,所以即使某个引用长期持有Context对象也不会引发内存泄露。
7. 主线程只做UI控制和Frameworks回调相关的事。附属线程只做费时的后台操作。交互只通过Handler。这样就可以避免大量的线程问题。
8. Frameworks的回调不要做太多事情仅做必要的初始化,其他不是很重要的事情可以放到其他线程中去做,或者用Handler Schele到稍后再做。
9. 要考虑多分辨率
至少为hdpi, mdpi, ldpi准备图片和布局。元素的单位也尽可能的使用dip而不要用px。
10. 利用Android手机的硬键
几乎所有的Android手机都有BACK和MENU,它们的作用是返回和弹出菜单,所以就不要再在UI中设计返回按扭和菜单按扭。很多优秀的应用如随手记和微信都有返回键,他们之所以有是因为他们都是从iOS上移植过来的,为了保存体验的一致,所以也有了返回和菜单。但这不够Android化,一个纯正的Android是没有必须重复硬键的功能的。

J. 每个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并发执行相关的资料

热点内容
java十进制十六进制转换 浏览:404
安卓手机怎么关闭识别物品 浏览:693
单片机通用烧录器 浏览:55
如何设置catia服务器开机运行 浏览:421
编程术语知多少 浏览:347
android模板代码下载 浏览:766
数据与程序员的区别 浏览:379
张勤编译青鸟 浏览:989
演出app哪个好 浏览:864
凤凰app推广开户哪个好 浏览:823
租服务器要关注什么 浏览:215
shell命令vi 浏览:673
javaem算法 浏览:588
闪送app哪里下载 浏览:654
java语言编译器词法分析 浏览:379
22岁程序员图片大全 浏览:954
ibm如何查看服务器raid 浏览:678
程序员那么可爱叶子是谁 浏览:716
gcc82编译器入口地址 浏览:693
上架一个服务器要做什么 浏览:854