Android如何調整執行緒呼叫棧大小
阿新 • • 發佈:2020-10-21
在常規的Android開發過程中,隨著業務邏輯越來越複雜,呼叫棧可能會越來越深,難免會遇到呼叫棧越界的情況,這種情況下,就需要調整執行緒棧的大小。
當然,主要還是增大執行緒棧大小,尤其是存在jni呼叫的情況下,C++層的棧開銷有時候是非常恐怖的,比如說遞迴呼叫。
這就需要分三種情況,主執行緒,自定義執行緒池,AsyncTask。
主執行緒的執行緒棧是沒有辦法進行修改的,這個沒辦法處理。
針對執行緒池的情況,需要在建立執行緒的時候,呼叫建構函式
public Thread(@RecentlyNullable ThreadGroup group,@RecentlyNullable Runnable target,@RecentlyNonNull String name,long stackSize)
通過設定stackSize
引數來解決問題。
參考程式碼如下:
import android.support.annotation.NonNull; import android.util.Log; import java.util.concurrent.ThreadFactory; /** * A ThreadFactory implementation which create new threads for the thread pool. */ public class SimpleThreadFactory implements ThreadFactory { private static final String TAG = "SimpleThreadFactory"; private final static ThreadGroup group = new ThreadGroup("SimpleThreadFactoryGroup"); // 工作執行緒堆疊大小調整為2MB private final static int workerStackSize = 2 * 1024 * 1024; @Override public Thread newThread(@NonNull final Runnable runnable) { final Thread thread = new Thread(group,runnable,"PoolWorkerThread",workerStackSize); // A exception handler is created to log the exception from threads thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { @Override public void uncaughtException(@NonNull Thread thread,@NonNull Throwable ex) { Log.e(TAG,thread.getName() + " encountered an error: " + ex.getMessage()); } }); return thread; } }
import android.support.annotation.AnyThread; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.util.Log; import java.util.concurrent.BlockingQueue; import java.util.concurrent.Callable; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; /** * A Singleton thread pool */ public class ThreadPool { private static final String TAG = "ThreadPool"; private static final int KEEP_ALIVE_TIME = 1; private static volatile ThreadPool sInstance = null; private static int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors(); private final ExecutorService mExecutor; private final BlockingQueue<Runnable> mTaskQueue; // Made constructor private to avoid the class being initiated from outside private ThreadPool() { // initialize a queue for the thread pool. New tasks will be added to this queue mTaskQueue = new LinkedBlockingQueue<>(); Log.d(TAG,"Available cores: " + NUMBER_OF_CORES); mExecutor = new ThreadPoolExecutor(NUMBER_OF_CORES,NUMBER_OF_CORES * 2,KEEP_ALIVE_TIME,TimeUnit.SECONDS,mTaskQueue,new SimpleThreadFactory()); } @NonNull @AnyThread public static ThreadPool getInstance() { if (null == sInstance) { synchronized (ThreadPool.class) { if (null == sInstance) { sInstance = new ThreadPool(); } } } return sInstance; } private boolean isThreadPoolAlive() { return (null != mExecutor) && !mExecutor.isTerminated() && !mExecutor.isShutdown(); } @Nullable @AnyThread public <T> Future<T> submitCallable(@NonNull final Callable<T> c) { synchronized (this) { if (isThreadPoolAlive()) { return mExecutor.submit(c); } } return null; } @Nullable @AnyThread public Future<?> submitRunnable(@NonNull final Runnable r) { synchronized (this) { if (isThreadPoolAlive()) { return mExecutor.submit(r); } } return null; } /* Remove all tasks in the queue and stop all running threads */ @AnyThread public void shutdownNow() { synchronized (this) { mTaskQueue.clear(); if ((!mExecutor.isShutdown()) && (!mExecutor.isTerminated())) { mExecutor.shutdownNow(); } } } }
針對AsyncTask的情況,一般是通過呼叫
public final AsyncTask<Params,Progress,Result> executeOnExecutor(Executor exec,Params... params)
指定執行緒池來執行,在特定的執行緒池中調整執行緒棧的大小。
參考程式碼如下:
import android.os.AsyncTask; import android.support.annotation.AnyThread; import android.support.annotation.NonNull; import android.util.Log; import java.util.concurrent.BlockingQueue; import java.util.concurrent.ExecutorService; import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.ThreadPoolExecutor; import java.util.concurrent.TimeUnit; public abstract class AsyncTaskEx<Params,Result> extends AsyncTask<Params,Result> { private static final String TAG = "AsyncTaskEx"; private static final int KEEP_ALIVE_TIME = 1; private static volatile ThreadPool sInstance = null; private static int NUMBER_OF_CORES = Runtime.getRuntime().availableProcessors(); private final ExecutorService mExecutor; private final BlockingQueue<Runnable> mTaskQueue; public AsyncTaskEx() { // initialize a queue for the thread pool. New tasks will be added to this queue mTaskQueue = new LinkedBlockingQueue<>(); Log.d(TAG,new SimpleThreadFactory()); } public AsyncTask<Params,Result> executeAsync(@NonNull final Params... params) { return super.executeOnExecutor(mExecutor,params); } /* Remove all tasks in the queue and stop all running threads */ @AnyThread public void shutdownNow() { synchronized (this) { mTaskQueue.clear(); if ((!mExecutor.isShutdown()) && (!mExecutor.isTerminated())) { mExecutor.shutdownNow(); } } } }
參考連結
- Increase AsyncTask stack size?
- StackOverFlowError: Stack size 1036KB in AsyncTask
- Android:增加呼叫堆疊大小
- AsyncTask和執行緒池
以上就是Android如何調整執行緒呼叫棧大小的詳細內容,更多關於Android 調整呼叫棧大小的資料請關注我們其它相關文章!