Android如何调整线程调用栈大小

在常规的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, Progress, Result> extends AsyncTask<Params, Progress, 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, "Available cores: " + NUMBER_OF_CORES);

    mExecutor = new ThreadPoolExecutor(NUMBER_OF_CORES, NUMBER_OF_CORES * 2, KEEP_ALIVE_TIME, TimeUnit.SECONDS, mTaskQueue, new SimpleThreadFactory());
  }

  public AsyncTask<Params, Progress, 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();
      }
    }
  }
}

参考链接

以上就是Android如何调整线程调用栈大小的详细内容,更多关于Android 调整调用栈大小的资料请关注我们其它相关文章!

(0)

相关推荐

  • Android线程池控制并发数多线程下载

    多线程下载并不是并发下载线程越多越好,因为当用户开启太多的并发线程之后,应用程序需要维护每条线程的开销,线程同步的开销. 这些开销反而会导致下载速度降低.因此需要避免在代码中直接开启大量线程执行下载. 主要实现步奏: 1.定义一个DownUtil类,下载工作基本在此类完成,在构造器中初始化UI线程的Handler.用于子线程和UI线程传递下载进度值. 2.所有的下载任务都保存在LinkedList.在init()方法中开启一个后台线程,不断地从LinkedList中取任务交给线程池中的空闲线程执

  • 完全解析Android多线程中线程池ThreadPool的原理和使用

    前言对于多线程,大家应该很熟悉.但是,大家了解线程池吗?今天,我将带大家全部学习关于线程池的所有知识. 目录 1. 简介 2. 工作原理 2.1 核心参数线程池中有6个核心参数,具体如下 上述6个参数的配置 决定了 线程池的功能,具体设置时机 = 创建 线程池类对象时 传入 ThreadPoolExecutor类 = 线程池的真正实现类 开发者可根据不同需求 配置核心参数,从而实现自定义线程池 // 创建线程池对象如下 // 通过 构造方法 配置核心参数 Executor executor =

  • Android之线程池ThreadPoolExecutor的简介

    Android中的线程池ThreadPoolExecutor解决了单线程下载数据的效率慢和线程阻塞的的问题,它的应用也是优化实现的方式.所以它的重要性不言而喻,但是它的复杂性也大,理解上可能会有问题,不过作为安卓工程师,了解这个也是必然的. ThreadPoolExecutor有几个构造函数,最多参数的构造函数最常用,下面会详细介绍各个参数的含义及其几个参数之间的关系: <span style="font-size:18px;">ThreadPoolExecutor(cor

  • Android子线程与更新UI问题的深入讲解

    前言 在Android项目中经常有碰到这样的问题,在子线程中完成耗时操作之后要更新UI,下面就自己经历的一些项目总结一下更新的方法.话不多说了,来一起看看详细的介绍吧 引子: 情形1 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView textView =

  • 浅谈Android中多线程切换的几种方法

    我们知道,多线程是Android开发中必现的场景,很多原生API和开源项目都有多线程的内容,这里简单总结和探讨一下常见的多线程切换方式. 我们先回顾一下Java多线程的几个基础内容,然后再分析总结一些经典代码中对于线程切换的实现方式. 几点基础 多线程切换,大概可以切分为这样几个内容:如何开启多个线程,如何定义每个线程的任务,如何在线程之间互相通信. Thread Thread可以解决开启多个线程的问题. Thread是Java中实现多线程的线程类,每个Thread对象都可以启动一个新的线程,注

  • Android 使用AsyncTask实现多线程断点续传

    前面一篇博客<AsyncTask实现断点续传>讲解了如何实现单线程下的断点续传,也就是一个文件只有一个线程进行下载.    对于大文件而言,使用多线程下载就会比单线程下载要快一些.多线程下载相比单线程下载要稍微复杂一点,本博文将详细讲解如何使用AsyncTask来实现多线程的断点续传下载. 一.实现原理 多线程下载首先要通过每个文件总的下载线程数(我这里设定5个)来确定每个线程所负责下载的起止位置. long blockLength = mFileLength / DEFAULT_POOL_S

  • Android开启新线程播放背景音乐

    在本实例用,开启一个新的线程播放背景音乐,在音乐文件播放完毕后,暂停5秒后重新开始播放. 具体实现: 界面(只有一个"开始"按钮) res/layout/main.xml: <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:t

  • Android开发经验谈:并发编程(线程与线程池)(推荐)

    一.线程 在Android开发中,你不可能都在主线程中开发,毕竟要联网,下载数据,保存数据等操作,当然这就离不开线程. (当然你可以在Android4.0以前的手机里在主线程请求网络,我最早开发的时候,用的手机比较古老...) 在Android中你可以随意创建线程,于是就会造成线程不可控,内存泄漏,创建线程消耗资源,线程太多了消耗资源等问题. 具体线程怎么创建我就不在文章里描述了,毕竟这主要将并发编程.... 大家知道线程不可控就好了...于是就需要对线程进行控制,防止一系列问题出现,这就用到了

  • Android线程中Handle的使用讲解

    Android UI线程是不安全的,子线程中进行UI操作,可能会导致程序的崩溃,解决办法:创建一个Message对象,然后借助Handler发送出去,之后在Handler的handleMessage()方法中获得刚才发送的Message对象,然后在这里进行UI操作就不会再出现崩溃了 定义类继承Handler public class BallHandler extends Handler{ ImageView imageview; Bitmap bitmap; public BallHandle

  • Android 使用AsyncTask实现多任务多线程断点续传下载

    这篇博客是AsyncTask下载系列的最后一篇文章,前面写了关于断点续传的和多线程下载的博客,这篇是在前两篇的基础上面实现的,有兴趣的可以去看下. 一.AsyncTask实现断点续传 二.AsyncTask实现多线程断点续传 这里模拟应用市场app下载实现了一个Demo,因为只有一个界面,所以没有将下载放到Service中,而是直接在Activity中创建.在正式的项目中,下载都是放到Service中,然后通过BroadCast通知界面更新进度. 上代码之前,先看下demo的运行效果图吧. 下面

随机推荐