崩溃bug日志总结3
目录介绍
- 1.1 OnErrorNotImplementedException【 Can't create handler inside thread that has not called Looper.prepare()】
- 1.2 adb.exe,start-server' failed -- run manually if necessary
- 1.3 java.lang.IllegalStateException: ExpectedBEGIN_OBJECT but was STRING at line 1 column 1 path $
- 1.4 android.content.ActivityNotFoundException: No Activity found to handle Intent
- 1.5 Package manager has died导致崩溃
- 1.6 IllegalArgumentException View添加窗口错误
- 1.7 IllegalStateException: Not allowed to start service Intent异常崩溃
- 1.8 java.lang.IllegalStateException:Can not perform this action after onSaveInstanceState
- 1.9 在Fragment中通过getActivity找不到上下文,报null导致空指针异常
好消息
- 博客笔记大汇总【16年3月到至今】,包括Java基础及深入知识点,Android技术博客,Python学习笔记等等,还包括平时开发中遇到的bug汇总,当然也在工作之余收集了大量的面试题,长期更新维护并且修正,持续完善……开源的文件是markdown格式的!同时也开源了生活博客,从12年起,积累共计47篇[近20万字],转载请注明出处,谢谢!
- 链接地址:https://github.com/yangchong211/YCBlogs
- 如果觉得好,可以star一下,谢谢!当然也欢迎提出建议,万事起于忽微,量变引起质变!
1.1 OnErrorNotImplementedException【 Can't create handler inside thread that has not called Looper.prepare()】
- A.详细崩溃日志信息
Can't create handler inside thread that has not called Looper.prepare()
- B.查看崩溃类信息
- C.项目中异常分析
- D.引发崩溃日志的流程分析
- 这是因为Handler对象与其调用者在同一线程中,如果在Handler中设置了延时操作,则调用线程也会堵塞。每个Handler对象都会绑定一个Looper对象,每个Looper对象对应一个消息队列(MessageQueue)。如果在创建Handler时不指定与其绑定的Looper对象,系统默认会将当前线程的Looper绑定到该Handler上。
- 在主线程中,可以直接使用new Handler()创建Handler对象,其将自动与主线程的Looper对象绑定;在非主线程中直接这样创建Handler则会报错,因为Android系统默认情况下非主线程中没有开启Looper,而Handler对象必须绑定Looper对象。
- 如果在主线程中创建handler时,系统会自动创建Looper,但是在子线程中创建handler时,是不会自动创建Looper的,此时如果不手动创建Looper,系统就会崩溃
- F.解决办法
- 不要在子线程中做UI操作,比如更改界面,吐司等等……
- 方法1:需先在该线程中手动开启Looper(Looper.prepare()-->Looper.loop()),然后将其绑定到Handler对象上;
final Runnable runnable = new Runnable() {
@Override
public void run() {
//执行耗时操作
try { Log.e("bm", "runnable线程: " + Thread.currentThread().getId()+ " name:" + Thread.currentThread().getName()); Thread.sleep(2000);
Log.e("bm", "执行完耗时操作了~");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
new Thread() {
public void run() {
Looper.prepare();
new Handler().post(runnable);//在子线程中直接去new 一个handler
Looper.loop(); //这种情况下,Runnable对象是运行在子线程中的,可以进行联网操作,但是不能更新UI
}
}.start();
- 方法2:通过Looper.getMainLooper(),获得主线程的Looper,将其绑定到此Handler对象上。
final Runnable runnable = new Runnable() {
@Override
public void run() {
//执行耗时操作
try {
Log.e("bm", "runnable线程: " + Thread.currentThread().getId()+ " name:" + Thread.currentThread().getName());
Thread.sleep(2000);
Log.e("bm", "执行完耗时操作了~");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
new Thread() {
public void run() {
//在子线程中直接去new 一个handler
new Handler(Looper.getMainLooper()).post(runnable);
//这种情况下,Runnable对象是运行在主线程中的,不可以进行联网操作,但是可以更新UI
}
}.start();
- G.其他延申
1.2 platform-tools\adb.exe,start-server' failed -- run manually if necessary
- A.详细崩溃日志信息
- B.查看崩溃类信息
- C.项目中异常分析
- adb启动失败,端口被占用
- D.引发崩溃日志的流程分析
- F.解决办法
百度google大家多说的是任务管理器 kill掉adb 或者重启adb server,但我任务管理器就没有adb ,猜测是某个程序占用了adb端口。于是按此思路查找。
5037为adb默认端口 查看该端口情况如下:
netstat -aon|findstr "5037"
TCP 127.0.0.1:5037 0.0.0.0:0 LISTENING 6540
发现6540占用了 5037端口,继续查看6540的task,发现是wandoujia .如下所示
tasklist|findstr "6540"
wandoujia_daemon.exe 6540 Console 1 4,276 K 接下来问题就好解决了,在任务管理器kill掉wandoujia_daemon.exe ,运行android程序,ok . 1.关闭xx荚进程
2.adb kill-server
3.adb start-server
- G.其他延申
1.3 java.lang.IllegalStateException: ExpectedBEGIN_OBJECT but was STRING at line 1 column 1 path $
- A.详细崩溃日志信息
- 非法参数,开始读取时应该是{}括号,所以需要处理String字符串,它有可能不是标准的json数据
java.lang.IllegalStateException: ExpectedBEGIN_OBJECT but was STRING at line 1 column 1 path $
- B.查看崩溃类信息
- C.项目中异常分析
- Gson解析数据出现问题,原因服务器返回数据不严谨
- D.引发崩溃日志的流程分析
- 可能的错误:
- bean类字段类型和字段名称不一致。
- 服务器访问得到的字符串不是纯json前面有空格和回车等字符(难发现)。
- 如果访问的json字符串不是utf-8编码时,用Gson解析会出这种问题,在日志中打印会发现json的{}前面有乱码字符,也需要注意一下。这是因为不同的编码的原因导致的,因此必须访问utf-8的json字符串,才会减少这种问题。
- 问题可能是:字符串并不是纯json字符串,开头可能会带有空字符或者回车符,这属于服务器问题,但我们也可以解决。
- 最重要原因的我们网络请求后结果是字符串,而不是json,因此需要处理。
- 可能的错误:
- F.解决办法
/**
* 判断是否是json结构。这种判断不是很严谨
*/
public static boolean isJson(String value) {
try {
new JSONObject(value);
} catch (JSONException e) {
return false;
}
return true;
} /**
* 判断是否是json结构
*/
public static boolean isGoodJson(String json) {
try {
new JsonParser().parse(json);
return true;
} catch (JsonParseException e) {
System.out.println("bad json: " + json);
return false;
}
}
- G.其他延申,补充说明
- 解决办法:后台输出稳定的Gson格式。此方法工程量太大
- 真正的问题是我的数据结构有问题
- 例如下面Json字符串:
- {"code":1,"info":"success","results":{"id":"1","name":"hehe"}}
- results对应的应该是一个实体类,如果这个时候想把他解析为String或者List就会出现异常
- 如果参考使用GsonForm处理后的数据模型,几乎不会出现问题;加入result后面的内容可能在请求时会因为某些原因会存在格式上的变化,这个时候就有出现该异常的风险。Gson中,关键字后面出现""引起来的内容将会被只认为是STRING,“{}”只被认为是类,“[]”只被认为是List,这个几乎是强制性的。
- 就是说如果你的实体预计是获取String的变量,但是关键字后面对应的却出现了“{”或“[”,那么这个转换将被认为是错误的,抛出异常。
1.4 android.content.ActivityNotFoundException: No Activity found to handle Intent
- A.详细崩溃日志信息
android.content.ActivityNotFoundException: No Activity found to handle Intent
- B.查看崩溃类信息
- 当调用{@link Context#startActivity}或其变体之一失败时,会引发此异常,因为无法找到执行给定意图的活动。
public class ActivityNotFoundException extends RuntimeException
{
public ActivityNotFoundException()
{
} public ActivityNotFoundException(String name)
{
super(name);
}
};
- C.项目中异常分析
- D.引发崩溃日志的流程分析
- F.解决办法
- 第一种办法:做一个try catch
Intent intent = new Intent(Intent.ACTION_SENDTO,url);
try {
context.startActivity(intent);
} catch(ActivityNotFoundException exception) {
Toast.makeText(this, "no activity", Toast.LENGTH_SHORT).show();
}
- 第二种办法:判断是否有应用宝客户端
//避免安装了应用宝的用户点击其他外部链接走此方法导致崩溃
//判断是否用应用宝客户端
if(AppUtils.isPkgInstalled(AdDetailActivity.this,"com.tencent.android.qqdownloader")){
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
startActivity( intent);
}
1.5 Package manager has died导致崩溃
- A.详细崩溃日志信息
出错代码位置
public static String softVersionName(Context context) {
PackageInfo info = null;
try {
info = context.getPackageManager().getPackageInfo( context.getPackageName(), 0); //在这里
} catch (NameNotFoundException e) {
e.printStackTrace();
}
return info.versionName;
}
- B.查看崩溃类信息
- C.项目中异常分析
- D.引发崩溃日志的流程分析
- 原因分析(Binder造成)
- 如果一个进程中使用的Binder内容超过了1M,就会crash.
- 如果Binder的使用超出了一个进程的限制就会抛出TransactionTooLargeException这个异常。
- 如果是其他原因造成Binder crash的话就会抛出RuntimeException。
- F.解决办法
public static String softVersionName(Context context) {
PackageInfo info = null;
try {//增加同步块
synchronized (context) {
info =context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
}
return info.versionName;
} catch (Exception e) {
e.printStackTrace();
return "";
}
}
- G.其他延申
private void test() {
//这个Demo就是同时创建两个线程来进行Binder调用.
for (int i = 0; i < 2; i++) {
new Thread() {
@Override
public void run() {
int count = 0;
List<PackageInfo> list = getPackageManager().getInstalledPackages(0);
for (PackageInfo info : list) {
if(count >=1000){
break;
}
try {
PackageInfo pi = getPackageManager().getPackageInfo(info.packageName, PackageManager.GET_ACTIVITIES);
} catch (PackageManager.NameNotFoundException e) { }
}
}
}.start();
}
}
}
- 错误打印日志
- 解决方式:其实只要避免多个线程同时来调用Binder就可以了,毕竟一个线程用了会释放,所以理论上是很难发生的。
synchronized(MainActivity.class){
PackageInfo pi = getPackageManager() .getPackageInfo(info.packageName, PackageManager.GET_ACTIVITIES);
}
1.6 IllegalArgumentException View添加窗口错误
- A.详细崩溃日志信息
View=com.android.internal.policy.impl.PhoneWindow$DecorView{22a4fb16 V.E..... R.....ID 0,0-1080,1020} not attached to window manager
com.flyco.dialog.widget.base.BaseDialog.superDismiss(BaseDialog.java)
- B.查看崩溃类信息
- C.项目中异常分析
- 该异常表示view没有添加到窗口管理器,通常是我们dismiss对话框的时候,activity已经不存在了,建议不要在非UI线程操作对话框。
- D.引发崩溃日志的流程分析
- 常发生这类Exception的情形都是,有一个费时的线程操作,需要显示一个Dialog,在任务开始的时候显示一个对话框,然后当任务完成了在Dismiss对话框,如果在此期间如果Activity因为某种原因被杀掉且又重新启动了,那么当dialog调用dismiss的时候WindowManager检查发现Dialog所属的Activity已经不存在,所以会报错。要避免此类Exception,就要正确的使用对话框,也要正确的使用线程
- F.解决办法
- 可以参考崩溃bug日志总结1中的1.7
- G.其他延申,建议
- 不要在非UI线程中使用对话框创建,显示和取消对话框;
- 尽量少用单独线程,出发是真正的耗时操作采用线程,线程也不要直接用Java式的匿名线程,除非是那种单纯的操作,操作完成不需要做其他事情的。
- 如果是在fragment中发起异步网络的回调中进行dialog的操作,那么在操作之前,需要判断 isAdd( ),避免fragment被回收了但是还要求dialog去dismiss
- 在Activity onDestroy中对Dialog提前进行关闭
1.7 IllegalStateException: Not allowed to start service Intent异常崩溃
- A.详细崩溃日志信息
Caused by: java.lang.IllegalStateException: Not allowed to start service Intent { act=initApplication cmp=com.paidian.hwmc/.service.InitializeService }: app is in background uid UidRecord{a37d28d u0a386 TRNB bg:+5m30s482ms idle procs:3 seq(0,0,0)}
- B.查看崩溃类信息
- C.项目中异常分析
- D.引发崩溃日志的流程分析
- F.解决办法
- G.其他延申
1.8 java.lang.IllegalStateException:Can not perform this action after onSaveInstanceState
A.详细崩溃日志信息
- B.查看崩溃类信息
- C.项目中异常分析
- 通过下面的源码分析,我们可以知道,出现以上崩溃日志的原因,是因为我们在按下页面返回键的时候,当前Activity以及在执行销毁操作(也就是说我们以前在其他地方调用了finish方法)。
- D.引发崩溃日志的流程分析
- 问题所在是Activity#onBackPressed()方法。查看源代码:点击onBackPressed方法中的super
- 在FragmentActivity中
@Override
public void onBackPressed() {
if (!mFragments.getSupportFragmentManager().popBackStackImmediate()) {
super.onBackPressed();
}
}
- 接着再次点击super,在Activity中
public void onBackPressed() {
if (mActionBar != null && mActionBar.collapseActionView()) {
return;
} if (!mFragments.getFragmentManager().popBackStackImmediate()) {
finishAfterTransition();
}
}
public void finishAfterTransition() {
if (!mActivityTransitionState.startExitBackTransition(this)) {
finish();
}
}
- 我们看到onBackPressed()方法执行了两个操作,第一个是获取当前的FragmentManager,并且执行退栈操作,第二个是在退栈完成之后,执行finish方法。继续查看源码,关键是FragmentManager实现类的popBackStackImmediate方法
@Override
public boolean popBackStackImmediate() {
checkStateLoss();
executePendingTransactions();
return popBackStackState(mHost.getHandler(), null, -1, 0);
}
- 我们看到,在执行退栈动作之前,这里还有一步检查操作
private void checkStateLoss() {
if (mStateSaved) {
throw new IllegalStateException(
"Can not perform this action after onSaveInstanceState");
}
if (mNoTransactionsBecause != null) {
throw new IllegalStateException(
"Can not perform this action inside of " + mNoTransactionsBecause);
}
}
- 从这里,我们终于找到了崩溃日志上的异常文案:Can not perform this action after onSaveInstanceState
- F.解决办法
- 方案1,在调用super.onBackPressed的时候,我们需要判断当前Activity是否正在执行销毁操作。
if (!isFinishing()) {
super.onBackPressed();
}
- 方案2,通过上面的源码分析,我们也知道了,super.onBackPressed最后也是调用finish()方法,因此我们可以重写onBackPressed,直接调用finish方法。
- G.其他延申
1.9 在Fragment中通过getActivity找不到上下文,报null导致空指针异常
- A.详细崩溃日志信息
- B.查看崩溃类信息
- C.项目中异常分析
- 使用ViewPager+Fragment进行视图滑动,在某些部分逻辑也许我们需要利用上下文Context(例如基本的Toast),但是由于Fragment只是衣服在Activity容器的一个试图,如果需要拿到当前的Activity的上下文Context就必须通过getActivity()获取。
- 遇过出现getActivity()出现null的时候导致程序报出空指针异常。其实原因可以归结于因为我们在
- 切换fragment的时候,会频繁被crash
- 系统内存不足
- 横竖屏幕切换的时候
- 以上情况都会导致Activity被系统回收,但是由于fragment的生命周期不会随着Actiivty被回收而被回收,因此才会导致getActivity()出现null的问题。
- 很多人都曾被这个问题所困扰,如果app长时间在后台运行,再次进入app的时候可能会出现crash,而且fragment会有重叠现象。如果系统内存不足、切换横竖屏、app长时间在后台运行,Activity都可能会被系统回收然后重建,但Fragment并不会随着Activity的回收而被回收,创建的所有Fragment会被保存到Bundle里面,从而导致Fragment丢失对应的Activity。
- D.引发崩溃日志的流程分析
- 当遇到getActivity()为null,或getContext()时,先冷静想想以下3点:
- 1.是不是放在了第三方的回调中
- 2.是不是在其他进程中调用了(其实第一点就是在其他进程中调用了)
- 3.是不是调用时不在指定生命周期范围内(onAttach与onDetach之间)
- 当遇到getActivity()为null,或getContext()时,先冷静想想以下3点:
- F.解决办法
在Fragment中直接调用
private MActivity mActivity;
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mActivity = (MActivity) activity;
}
@Override
public void onDetach() {
super.onDetach();
mActivity = null;
}
- G.其他延申
- 源码解读:在FragmentActivity中
@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Parcelable p = mFragments.saveAllState();
if (p != null) {
outState.putParcelable(FRAGMENTS_TAG, p);
}
……
}
- 如果从最近使用的应用里面点击我们的应用,系统会恢复之前被回收的Activity,这个时候FragmentActivity在oncreate里面也会做Fragment的恢复
@SuppressWarnings("deprecation")
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
mFragments.attachHost(null /*parent*/);
super.onCreate(savedInstanceState);
NonConfigurationInstances nc = (NonConfigurationInstances) getLastNonConfigurationInstance();
if (nc != null) {
mFragments.restoreLoaderNonConfig(nc.loaders);
}
if (savedInstanceState != null) {
Parcelable p = savedInstanceState.getParcelable(FRAGMENTS_TAG);
mFragments.restoreAllState(p, nc != null ? nc.fragments : null);
……
}
if (mPendingFragmentActivityResults == null) {
mPendingFragmentActivityResults = new SparseArrayCompat<>();
mNextCandidateRequestIndex = 0;
}
mFragments.dispatchCreate();
}
- 假设我们的页面叫MyActivity(继承自FragmentActivity),其中用到的Fragment叫MyFragment。出现上面这种情况时,app发生的变化如下:
- 1、在前面提到的几种情况下系统回收了MyActivity
- 2、通过onSaveInstanceState保存MyFragment的状态
- 3、用户再次点击进入app
- 4、由于MyActivity被回收,系统会重启MyActivity,根据之前保存的MyFragment的状态恢复fragment
- 5、MyActivity的代码逻辑中,会再次创建新的MyFragment
- 6、页面出现混乱,覆盖了两层的fragment。假如恢复的MyFragment使用到了getActivity()方法,会报空指针异常
- 对于上面的问题,可以考虑下面这两种解决办法:
- 1、不保存fragment的状态:在MyActivity中重写onSaveInstanceState方法,将super.onSaveInstanceState(outState);注释掉,让其不再保存Fragment的状态,达到fragment随MyActivity一起销毁的目的。
- 2、重建时清除已经保存的fragment的状态:在恢复Fragment之前把Bundle里面的fragment状态数据给清除。方法如下:
if(savedInstanceState!= null){
String FRAGMENTS_TAG = "Android:support:fragments";
savedInstanceState.remove(FRAGMENTS_TAG);
}
关于其他内容介绍
01.关于博客汇总链接
02.关于我的博客
- 我的个人站点:www.yczbj.org,www.ycbjie.cn
- github:https://github.com/yangchong211
- 知乎:https://www.zhihu.com/people/yang-chong-69-24/pins/posts
- 简书:http://www.jianshu.com/u/b7b2c6ed9284
- csdn:http://my.csdn.net/m0_37700275
- 喜马拉雅听书:http://www.ximalaya.com/zhubo/71989305/
- 开源中国:https://my.oschina.net/zbj1618/blog
- 泡在网上的日子:http://www.jcodecraeer.com/member/content_list.php?channelid=1
- 邮箱:yangchong211@163.com
- 阿里云博客:https://yq.aliyun.com/users/article?spm=5176.100- 239.headeruserinfo.3.dT4bcV
- segmentfault头条:https://segmentfault.com/u/xiangjianyu/articles
崩溃bug日志总结3的更多相关文章
- C++后台服务崩溃堆栈日志
C++后台服务崩溃堆栈日志 C/C++后台服务运行过程中总会出现一些不容易重现的崩溃故障,由于重现频率低,同时运行在服务器上,导致无法调试,此外服务直接崩溃,常规日志无法截获到有用信息,这时如果能够保 ...
- android 程序崩溃crash日志的捕捉
android 程序崩溃crash日志的捕捉 之前在项目开发过程中,一直会遇到程序崩溃了,但是测试組的哥哥们又没及时的导出日志.... 后来在诳群的时候听别人说起,腾讯有那么一个叫bugly的东西 将 ...
- 谦先生的bug日志之hive启动权限问题
上海尚学堂谦先生的bug日志之hive启动权限问题 这几天开始做新老集群的迁移,今天开始对hive的所有数据进行迁移,主要是表的元信息和表数据.表的元信息我们存在mysql中,跟hive的服务器并不在 ...
- UNITY崩溃的日志
有关UNITY的日志,有两个路径. 1,一般日志路径:C:/Users/xxxx/ AppData/Local/Unity/Editor,此文件夹下有三个文件 ,如下图:Editor.log, Edi ...
- Python 中 对logging 模块进行封装,记录bug日志、日志等级
是程序产生的日志 程序员自定义设置的 收集器和渠道级别那个高就以那个级别输出 日志和报告的作用: 报告的重点在于执行结果(执行成功失败,多少用例覆盖),返回结果 日志的重点在执行过程当中,异常点,哪里 ...
- 漫谈:从APP崩溃率标准,到Monkey介绍拓展Maxim,及Jenkins自动化配置,持续集成获取崩溃monkey日志
漫谈:从APP崩溃率标准,到Monkey介绍拓展Maxim,及Jenkins自动化配置,持续集成获取崩溃日志 1.APP崩溃率标准 开发或测试app的同学,对于app崩溃肯定非常熟悉,频繁的线上崩溃属 ...
- 番外特别篇之 为什么我不建议你直接使用UIImage传值?--从一个诡异的相册九图连读崩溃bug谈起
关于"番外特别篇" 所谓"番外特别篇",就是系列文章更新期间内,随机插入的一篇文章.目前我正在更新的系列文章是 实现iOS图片等资源文件的热更新化.但是,这两天 ...
- 内存转储文件调试系统崩溃bug
百度百科:内存转储文件 内存转储是用于系统崩溃时,将内存中的数据转储保存在转储文件中,供给有关人员进行排错分析用途.而它所保存生成的文件就叫做内存转储文件. 内存转储文件也被称作虚拟内存,它是用硬盘里 ...
- bug日志-天坑,Spring Security的登陆报错:An internal error occurred while trying to authenticate the user.
在学习Spring Security的时候,我的编辑器给我报错:An internal error occurred while trying to authenticate the user. 明明 ...
- 新版本读取老版本文件崩溃BUG
读取文件匹配代码 BOOL CWBPage::LoadFromFile(CFile *pFile, LONGLONG& lOff, ULONGLONG lFileLength) { if (p ...
随机推荐
- 《ASP.ENT Core 与 RESTful API 开发实战》(第3章)-- 读书笔记(中)
第 3 章 ASP.NET Core 核心特性 3.3 依赖注入 通常情况下,应用程序由多个组件构成,而组件与组件之间往往存在依赖关系 当我们需要获取数据时,通常的做法是实例化依赖的类,然后调用类里面 ...
- 使用vscode 用git 拉取代码,提示:在签出前,请清理存储库工作树
使用vscode 用git 拉取代码,提示:在签出前,请清理存储库工作树 如图: 问题: git仓库上的代码和本地代码存在冲突了所以会报这个报错. 解决办法: 手动解决①git stash 先将本地修 ...
- SP16113 SUBTLEBA - Trucks Transportation 题解
题目传送门 前言 本题样例有问题,如果想要样例可以去 vjudge 上. 本题提交后可能会出现 UKE ,建议前往 link 提交,而且本篇题解中所提供的代码也为 link 代码. 前置知识 Krus ...
- 《.NET物联网从零开始系列》-开篇
近日搞硬件网关时,那些残存的数电.模电和通信原理的记忆时常在脑海中萦绕: 想起来多年前看张高兴的博客学会了.netcore+树莓派进行物联网开发. 使用dragonboard(龙板)搭载windows ...
- acm数学总结
1.给定两个质数,m, n, 大于n * m - n - m的数都可以被整数个n和m唯一组成. 相关习题:[Coins] (https://ac.nowcoder.com/acm/contest/34 ...
- win32 - 将线程重定向到另一个函数(附带Suspend的解释)
Suspend: 挂起指定的线程 备注:不要永远挂起线程, 因为在Win32中,进程堆是线程安全的对象,并且由于在不访问堆的情况下很难在Win32中完成很多工作,因此在Win32中挂起线程极有可能使进 ...
- Selenium入门介绍
目录 Selenium概述 浏览器支持 工具库 开发实践 等待 操作浏览器 定位元素 定位单个元素 定位多个元素 获取HTML元素内容的方式 Selenium概述 https://github.com ...
- logback 常用配置(详解)
转自:https://blog.csdn.net/qq_36850813/article/details/83092051 官方文档参考:https://logback.qos.ch/manual/a ...
- 【算法day3】小和、荷兰国旗、快排
小和问题 现有数组[1,3,4,2,5] 1左边是0(小于1),所以1的小和为0 3左边是1(小于3),所以3的小和为1 4左边是1.3(均小于4),所以4的小和为1+3=4 2左边是1.3.4(只有 ...
- 简化Simulink的建模与模型重构
简化Simulink的建模与模型重构 模型重构 Simulink作为汽车和自动化领域中经典的模型工程必备工具,不管是专业的汽车控制器的开发还是自动化控制的专业应用编程,都会使用到Simulink进行图 ...