Android如何调整线程调用栈大小
在常规的Android开发过程中,随着业务逻辑越来越复杂,调用栈可能会越来越深,难免会遇到调用栈越界的情况,这种情况下,就需要调整线程栈的大小。
当然,主要还是增大线程栈大小,尤其是存在jni调用的情况下,C++层的栈开销有时候是非常恐怖的,比如说递归调用。
这就需要分三种情况,主线程,自定义线程池,AsyncTask。
主线程的线程栈是没有办法进行修改的,这个没办法处理。
针对线程池的情况,需要在创建线程的时候,调用构造函数
publicThread(@RecentlyNullableThreadGroupgroup,@RecentlyNullableRunnabletarget,@RecentlyNonNullStringname,longstackSize)
通过设置stackSize参数来解决问题。
参考代码如下:
importandroid.support.annotation.NonNull;
importandroid.util.Log;
importjava.util.concurrent.ThreadFactory;
/**
*AThreadFactoryimplementationwhichcreatenewthreadsforthethreadpool.
*/
publicclassSimpleThreadFactoryimplementsThreadFactory{
privatestaticfinalStringTAG="SimpleThreadFactory";
privatefinalstaticThreadGroupgroup=newThreadGroup("SimpleThreadFactoryGroup");
//工作线程堆栈大小调整为2MB
privatefinalstaticintworkerStackSize=2*1024*1024;
@Override
publicThreadnewThread(@NonNullfinalRunnablerunnable){
finalThreadthread=newThread(group,runnable,"PoolWorkerThread",workerStackSize);
//Aexceptionhandleriscreatedtologtheexceptionfromthreads
thread.setUncaughtExceptionHandler(newThread.UncaughtExceptionHandler(){
@Override
publicvoiduncaughtException(@NonNullThreadthread,@NonNullThrowableex){
Log.e(TAG,thread.getName()+"encounteredanerror:"+ex.getMessage());
}
});
returnthread;
}
}
importandroid.support.annotation.AnyThread;
importandroid.support.annotation.NonNull;
importandroid.support.annotation.Nullable;
importandroid.util.Log;
importjava.util.concurrent.BlockingQueue;
importjava.util.concurrent.Callable;
importjava.util.concurrent.ExecutorService;
importjava.util.concurrent.Future;
importjava.util.concurrent.LinkedBlockingQueue;
importjava.util.concurrent.ThreadPoolExecutor;
importjava.util.concurrent.TimeUnit;
/**
*ASingletonthreadpool
*/
publicclassThreadPool{
privatestaticfinalStringTAG="ThreadPool";
privatestaticfinalintKEEP_ALIVE_TIME=1;
privatestaticvolatileThreadPoolsInstance=null;
privatestaticintNUMBER_OF_CORES=Runtime.getRuntime().availableProcessors();
privatefinalExecutorServicemExecutor;
privatefinalBlockingQueuemTaskQueue;
//Madeconstructorprivatetoavoidtheclassbeinginitiatedfromoutside
privateThreadPool(){
//initializeaqueueforthethreadpool.Newtaskswillbeaddedtothisqueue
mTaskQueue=newLinkedBlockingQueue<>();
Log.d(TAG,"Availablecores:"+NUMBER_OF_CORES);
mExecutor=newThreadPoolExecutor(NUMBER_OF_CORES,NUMBER_OF_CORES*2,KEEP_ALIVE_TIME,TimeUnit.SECONDS,mTaskQueue,newSimpleThreadFactory());
}
@NonNull
@AnyThread
publicstaticThreadPoolgetInstance(){
if(null==sInstance){
synchronized(ThreadPool.class){
if(null==sInstance){
sInstance=newThreadPool();
}
}
}
returnsInstance;
}
privatebooleanisThreadPoolAlive(){
return(null!=mExecutor)&&!mExecutor.isTerminated()&&!mExecutor.isShutdown();
}
@Nullable
@AnyThread
publicFuturesubmitCallable(@NonNullfinalCallablec){
synchronized(this){
if(isThreadPoolAlive()){
returnmExecutor.submit(c);
}
}
returnnull;
}
@Nullable
@AnyThread
publicFuture>submitRunnable(@NonNullfinalRunnabler){
synchronized(this){
if(isThreadPoolAlive()){
returnmExecutor.submit(r);
}
}
returnnull;
}
/*Removealltasksinthequeueandstopallrunningthreads
*/
@AnyThread
publicvoidshutdownNow(){
synchronized(this){
mTaskQueue.clear();
if((!mExecutor.isShutdown())&&(!mExecutor.isTerminated())){
mExecutor.shutdownNow();
}
}
}
}
针对AsyncTask的情况,一般是通过调用
publicfinalAsyncTaskexecuteOnExecutor(Executorexec,Params...params)
指定线程池来运行,在特定的线程池中调整线程栈的大小。
参考代码如下:
importandroid.os.AsyncTask; importandroid.support.annotation.AnyThread; importandroid.support.annotation.NonNull; importandroid.util.Log; importjava.util.concurrent.BlockingQueue; importjava.util.concurrent.ExecutorService; importjava.util.concurrent.LinkedBlockingQueue; importjava.util.concurrent.ThreadPoolExecutor; importjava.util.concurrent.TimeUnit; publicabstractclassAsyncTaskExextendsAsyncTask { privatestaticfinalStringTAG="AsyncTaskEx"; privatestaticfinalintKEEP_ALIVE_TIME=1; privatestaticvolatileThreadPoolsInstance=null; privatestaticintNUMBER_OF_CORES=Runtime.getRuntime().availableProcessors(); privatefinalExecutorServicemExecutor; privatefinalBlockingQueue mTaskQueue; publicAsyncTaskEx(){ //initializeaqueueforthethreadpool.Newtaskswillbeaddedtothisqueue mTaskQueue=newLinkedBlockingQueue<>(); Log.d(TAG,"Availablecores:"+NUMBER_OF_CORES); mExecutor=newThreadPoolExecutor(NUMBER_OF_CORES,NUMBER_OF_CORES*2,KEEP_ALIVE_TIME,TimeUnit.SECONDS,mTaskQueue,newSimpleThreadFactory()); } publicAsyncTask executeAsync(@NonNullfinalParams...params){ returnsuper.executeOnExecutor(mExecutor,params); } /*Removealltasksinthequeueandstopallrunningthreads */ @AnyThread publicvoidshutdownNow(){ synchronized(this){ mTaskQueue.clear(); if((!mExecutor.isShutdown())&&(!mExecutor.isTerminated())){ mExecutor.shutdownNow(); } } } }
参考链接
- IncreaseAsyncTaskstacksize?
- StackOverFlowError:Stacksize1036KBinAsyncTask
- Android:增加调用堆栈大小
- AsyncTask和线程池
以上就是Android如何调整线程调用栈大小的详细内容,更多关于Android调整调用栈大小的资料请关注毛票票其它相关文章!