diff --git a/app/src/main/java/com/gh/base/GHThreadFactory.kt b/app/src/main/java/com/gh/base/GHThreadFactory.kt new file mode 100644 index 0000000000..9bb468e288 --- /dev/null +++ b/app/src/main/java/com/gh/base/GHThreadFactory.kt @@ -0,0 +1,17 @@ +package com.gh.base + +import java.util.concurrent.ThreadFactory +import java.util.concurrent.atomic.AtomicInteger + +class GHThreadFactory(threadNamePrefix: String) : ThreadFactory { + + private val THREAD_NAME_STEM = "${threadNamePrefix}_%d" + private val mThreadId = AtomicInteger(0) + + override fun newThread(r: Runnable?): Thread { + val t = Thread(r) + t.name = String.format(THREAD_NAME_STEM, mThreadId.getAndIncrement()) + return t + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/gh/common/AppExecutor.kt b/app/src/main/java/com/gh/common/AppExecutor.kt index a82b545dcf..9713ab42ec 100644 --- a/app/src/main/java/com/gh/common/AppExecutor.kt +++ b/app/src/main/java/com/gh/common/AppExecutor.kt @@ -2,12 +2,13 @@ package com.gh.common import android.os.Handler import android.os.Looper +import com.gh.base.GHThreadFactory import com.gh.common.AppExecutor.ioExecutor import com.gh.common.AppExecutor.lightWeightIoExecutor +import com.gh.common.AppExecutor.logExecutor import com.gh.common.AppExecutor.uiExecutor import io.reactivex.schedulers.Schedulers -import java.util.concurrent.Executor -import java.util.concurrent.Executors +import java.util.concurrent.* /** * APP 线程池管理类 @@ -15,16 +16,30 @@ import java.util.concurrent.Executors * [ioExecutor] 是一个最大线程数固定的线程池,较为繁重的 IO 任务可以交给它 * [uiExecutor] 是主线程的包裹,需要切换至主线程执行可以用它 * [lightWeightIoExecutor] 是一个单线程的线程池,轻量级且需要保证同一线程的 IO 任务可以交给它 - * + * [logExecutor] 只为上传 log 而使用的线程池 */ object AppExecutor { + private val mCoreSize = Runtime.getRuntime().availableProcessors() + private val mMinimumPoolSize = 6.coerceAtLeast(mCoreSize * 2) + private val mMaximumPoolSize = 32.coerceAtLeast(mCoreSize * 8) + @JvmStatic val uiExecutor by lazy { MainThreadExecutor() } + @JvmStatic - val lightWeightIoExecutor by lazy { Executors.newSingleThreadExecutor() } + val lightWeightIoExecutor by lazy { Executors.newSingleThreadExecutor(GHThreadFactory("GH_LIGHT_WEIGHT_IO_THREAD")) } + @JvmStatic - val ioExecutor = Executors.newCachedThreadPool() // 用 by lazy 可能影响初始化速度 + val logExecutor by lazy { Executors.newSingleThreadExecutor(GHThreadFactory("GH_LOG_THREAD")) } + + @JvmStatic + val ioExecutor = ThreadPoolExecutor( + mMinimumPoolSize, + mMaximumPoolSize, + 20L, TimeUnit.SECONDS, + LinkedBlockingQueue(1000), + GHThreadFactory("GH_IO_THREAD")) val cachedScheduler by lazy { Schedulers.from(ioExecutor) } diff --git a/app/src/main/java/com/gh/common/FixedRateJobHelper.kt b/app/src/main/java/com/gh/common/FixedRateJobHelper.kt index d8fec8e641..f111e144a0 100644 --- a/app/src/main/java/com/gh/common/FixedRateJobHelper.kt +++ b/app/src/main/java/com/gh/common/FixedRateJobHelper.kt @@ -11,6 +11,7 @@ import com.gh.gamecenter.entity.TimeEntity import com.gh.gamecenter.retrofit.Response import com.gh.gamecenter.retrofit.RetrofitManager import com.halo.assistant.HaloApp +import io.reactivex.schedulers.Schedulers import kotlin.concurrent.fixedRateTimer object FixedRateJobHelper { @@ -35,7 +36,7 @@ object FixedRateJobHelper { // 时间校对,10分钟一次 if ((mExecuteCount * CHECKER_PERIOD) % TIME_PERIOD == 0L) { RetrofitManager.getInstance(HaloApp.getInstance().application).api.time - .subscribeOn(AppExecutor.cachedScheduler) + .subscribeOn(Schedulers.io()) .subscribe(object : Response() { override fun onResponse(response: TimeEntity?) { val serverTime = response?.time diff --git a/app/src/main/java/com/gh/common/TimeElapsedHelper.kt b/app/src/main/java/com/gh/common/TimeElapsedHelper.kt index 004a14160e..b5e4c97a0c 100644 --- a/app/src/main/java/com/gh/common/TimeElapsedHelper.kt +++ b/app/src/main/java/com/gh/common/TimeElapsedHelper.kt @@ -5,6 +5,7 @@ import android.app.Application import android.os.Bundle import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager +import com.gh.base.GHThreadFactory import com.halo.assistant.HaloApp import java.util.concurrent.ExecutorService import java.util.concurrent.Executors @@ -114,7 +115,7 @@ class TimeElapsedHelper(val fragment: Fragment?, val activity: Activity?) { } object TimeElapsedThreadHolder { - val threadService: ExecutorService by lazy { Executors.newSingleThreadExecutor() } + val threadService: ExecutorService by lazy { Executors.newSingleThreadExecutor(GHThreadFactory("TIME_ELAPSED_THREAD")) } } interface TimeoutCallback { diff --git a/app/src/main/java/com/gh/common/exposure/ExposureManager.kt b/app/src/main/java/com/gh/common/exposure/ExposureManager.kt index 5af9e08ed3..5db4523ef3 100644 --- a/app/src/main/java/com/gh/common/exposure/ExposureManager.kt +++ b/app/src/main/java/com/gh/common/exposure/ExposureManager.kt @@ -9,7 +9,7 @@ import com.gh.loghub.LgLOG import com.gh.loghub.LoghubHelper import com.halo.assistant.HaloApp import com.lightgame.utils.Utils -import java.util.concurrent.Executors +import java.util.concurrent.ExecutorService /** * A handful tool for committing logs to aliyun loghub. @@ -31,15 +31,15 @@ object ExposureManager { // exposureCache 用来过滤掉具有相同 id 的曝光事件,避免重复发送事件 private val exposureSet by lazy { hashSetOf() } - private val exposureExecutor by lazy { Executors.newSingleThreadExecutor() } + private var exposureExecutor: ExecutorService? = null private val exposureCache by lazy { FixedSizeLinkedHashSet(300) } private val exposureDao by lazy { ExposureDatabase.buildDatabase(HaloApp.getInstance().application).logHubEventDao() } @JvmStatic - fun init() { + fun init(excutor: ExecutorService) { loghubHelper.init(HaloApp.getInstance().application, ENDPOINT, PROJECT, LOG_STORE) { TimeUtil.currentTimeMillis() } - - exposureExecutor.execute { + exposureExecutor = excutor + exposureExecutor?.execute { val eventList = exposureDao.getAll() exposureSet.addAll(eventList) } @@ -49,7 +49,7 @@ object ExposureManager { * Log a single exposure event. */ fun log(event: ExposureEvent) { - exposureExecutor.execute { + exposureExecutor?.execute { try { if (!exposureCache.contains(event.id)) { // Catch `android.database.sqlite.SQLiteFullException: database or disk is full` exception. @@ -71,7 +71,7 @@ object ExposureManager { * Log a collection of exposure event. */ fun log(eventList: List) { - exposureExecutor.execute { + exposureExecutor?.execute { for (event in eventList) { try { if (!exposureCache.contains(event.id)) { @@ -94,7 +94,7 @@ object ExposureManager { * @param forced Ignore all restrictions. */ fun commitSavedExposureEvents(forced: Boolean = false) { - exposureExecutor.execute { + exposureExecutor?.execute { tryWithDefaultCatch { // TODO 初始化 loghubHelper 去掉这个 tryCatch 块 if (exposureSet.size < STORE_SIZE && !forced || exposureSet.size == 0) return@execute diff --git a/app/src/main/java/com/gh/common/filter/RegionSettingHelper.kt b/app/src/main/java/com/gh/common/filter/RegionSettingHelper.kt index 2f72b80684..726c7945e3 100644 --- a/app/src/main/java/com/gh/common/filter/RegionSettingHelper.kt +++ b/app/src/main/java/com/gh/common/filter/RegionSettingHelper.kt @@ -1,7 +1,6 @@ package com.gh.common.filter import android.annotation.SuppressLint -import com.gh.common.AppExecutor import com.gh.common.constant.Constants import com.gh.common.util.SPUtils import com.gh.common.util.debounceActionWithInterval @@ -14,6 +13,7 @@ import com.gh.gamecenter.retrofit.RetrofitManager import com.halo.assistant.HaloApp import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.functions.Function +import io.reactivex.schedulers.Schedulers object RegionSettingHelper { @@ -67,7 +67,7 @@ object RegionSettingHelper { RetrofitManager.getInstance(HaloApp.getInstance().application) .sensitiveApi .getRegionSetting(HaloApp.getInstance().channel) - .subscribeOn(AppExecutor.cachedScheduler) + .subscribeOn(Schedulers.io()) .observeOn(AndroidSchedulers.mainThread()) .subscribe(object : BiResponse() { override fun onSuccess(data: RegionSetting) { diff --git a/app/src/main/java/com/gh/common/loghub/LoghubUtils.kt b/app/src/main/java/com/gh/common/loghub/LoghubUtils.kt index 89d5f317be..f9485c3019 100644 --- a/app/src/main/java/com/gh/common/loghub/LoghubUtils.kt +++ b/app/src/main/java/com/gh/common/loghub/LoghubUtils.kt @@ -9,7 +9,7 @@ import com.gh.common.exposure.meta.Meta import com.gh.common.util.tryWithDefaultCatch import com.gh.loghub.LoghubHelper import org.json.JSONObject -import java.util.concurrent.Executors +import java.util.concurrent.ExecutorService object LoghubUtils { @@ -17,14 +17,15 @@ object LoghubUtils { private lateinit var mApplication: Application private val loghubEventSet by lazy { hashSetOf() } - private val loghubEventExecutor by lazy { Executors.newSingleThreadExecutor() } + private var loghubEventExecutor: ExecutorService? = null private val loghubEventDao by lazy { LoghubDatabase.buildDatabase(mApplication).logHubEventDao() } @JvmStatic - fun init(application: Application) { + fun init(application: Application, executor: ExecutorService) { mApplication = application - loghubEventExecutor.execute { + loghubEventExecutor = executor + loghubEventExecutor?.execute { val eventList = loghubEventDao.getAll() loghubEventSet.addAll(eventList) } @@ -32,7 +33,7 @@ object LoghubUtils { @JvmStatic fun log(logJson: JSONObject, logStore: String, forcedUpload: Boolean) { - loghubEventExecutor.execute { + loghubEventExecutor?.execute { try { val event = LoghubEvent(time = (System.currentTimeMillis() / 1000L).toString(), content = logJson.toString(), logStore = logStore) loghubEventSet.add(event) @@ -49,7 +50,7 @@ object LoghubUtils { @JvmStatic fun log(jsonString: String, logStore: String, forcedUpload: Boolean) { - loghubEventExecutor.execute { + loghubEventExecutor?.execute { try { val event = LoghubEvent(time = (System.currentTimeMillis() / 1000L).toString(), content = jsonString, logStore = logStore) loghubEventSet.add(event) @@ -69,7 +70,7 @@ object LoghubUtils { } fun commitSavedLoghubEvents() { - loghubEventExecutor.execute { + loghubEventExecutor?.execute { // TODO 初始化 loghubHelper 去掉这个 tryCatch 块 tryWithDefaultCatch { if (loghubEventSet.isEmpty()) return@execute diff --git a/app/src/main/java/com/gh/common/util/UsageStatsHelper.kt b/app/src/main/java/com/gh/common/util/UsageStatsHelper.kt index d01b3a4e2c..5602a024a3 100644 --- a/app/src/main/java/com/gh/common/util/UsageStatsHelper.kt +++ b/app/src/main/java/com/gh/common/util/UsageStatsHelper.kt @@ -25,7 +25,6 @@ import com.gh.gamecenter.retrofit.BiResponse import com.gh.gamecenter.retrofit.RetrofitManager import com.halo.assistant.HaloApp import com.lightgame.utils.Utils -import io.reactivex.schedulers.Schedulers import okhttp3.MediaType import okhttp3.RequestBody import okhttp3.ResponseBody @@ -174,8 +173,6 @@ object UsageStatsHelper { val body = RequestBody.create(MediaType.parse("application/json"), postBody.toString()) mApi.postUsageStatus(body, UserManager.getInstance().userId) - .subscribeOn(Schedulers.io()) - .observeOn(Schedulers.io()) .subscribe(object : BiResponse() { override fun onSuccess(data: ResponseBody) { debugOnly { @@ -222,8 +219,6 @@ object UsageStatsHelper { } mApi.getUsageStatusUpdateTime(HaloApp.getInstance().gid) - .subscribeOn(Schedulers.io()) - .observeOn(Schedulers.io()) .subscribe(object : BiResponse() { override fun onSuccess(data: ResponseBody) { val body = JSONObject(data.string()) diff --git a/app/src/main/java/com/gh/common/videolog/VideoRecordUtils.kt b/app/src/main/java/com/gh/common/videolog/VideoRecordUtils.kt index a82dfc46a8..6c3a27145d 100644 --- a/app/src/main/java/com/gh/common/videolog/VideoRecordUtils.kt +++ b/app/src/main/java/com/gh/common/videolog/VideoRecordUtils.kt @@ -11,28 +11,29 @@ import com.halo.assistant.HaloApp import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.schedulers.Schedulers import okhttp3.ResponseBody -import java.util.concurrent.Executors +import java.util.concurrent.ExecutorService object VideoRecordUtils { private const val STORE_SIZE = 20 private lateinit var mApplication: Application private val videoRecordSet by lazy { hashSetOf() } - private val videoRecordExecutor by lazy { Executors.newSingleThreadExecutor() } + private var videoRecordExecutor: ExecutorService? = null private val videoRecordDao by lazy { AppDatabase.getInstance(mApplication).videoRecordDao() } @JvmStatic - fun init(application: Application) { + fun init(application: Application, executor : ExecutorService) { mApplication = application - videoRecordExecutor.execute { + videoRecordExecutor = executor + videoRecordExecutor?.execute { val recordList = videoRecordDao.getAll() videoRecordSet.addAll(recordList) } } fun log(videoId: String) { - videoRecordExecutor.execute { + videoRecordExecutor?.execute { try { val entity = VideoRecordEntity(videoId = videoId, time = System.currentTimeMillis() / 1000L) videoRecordSet.add(entity) @@ -48,7 +49,7 @@ object VideoRecordUtils { fun commitVideoRecord() { if (videoRecordSet.isEmpty() || !::mApplication.isInitialized) return - videoRecordExecutor.execute { + videoRecordExecutor?.execute { uploadVideoRecord() val exposureList = videoRecordSet.toList() videoRecordSet.removeAll(exposureList) diff --git a/app/src/main/java/com/gh/gamecenter/MainActivity.java b/app/src/main/java/com/gh/gamecenter/MainActivity.java index f1908eafeb..8ab8aab322 100644 --- a/app/src/main/java/com/gh/gamecenter/MainActivity.java +++ b/app/src/main/java/com/gh/gamecenter/MainActivity.java @@ -437,19 +437,6 @@ public class MainActivity extends BaseActivity { } } - // 统计下载 - private void uploadData(String id, String platform) { - Map params = new HashMap<>(); - params.put("game", id); - params.put("platform", platform); - RequestBody body = RequestBody.create(MediaType.parse("application/json"), - new JSONObject(params).toString()); - RetrofitManager.getInstance(this).getApi().postDownload(body) - .subscribeOn(Schedulers.io()) - .observeOn(AndroidSchedulers.mainThread()) - .subscribe(new Response<>()); - } - @Override public boolean onKeyDown(int keyCode, KeyEvent event) { if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0 && !mMainWrapperFragment.onHandleBackPressed()) { @@ -724,7 +711,7 @@ public class MainActivity extends BaseActivity { public void onEventMainThread(EBNetworkState busNetworkState) { if (busNetworkState.isNetworkConnected()) { if (Config.getSettings() == null) { - Config.getGhzsSettings(); + AppExecutor.getIoExecutor().execute(Config::getGhzsSettings); } mPackageViewModel.checkData(); diff --git a/app/src/main/java/com/gh/gamecenter/baselist/ListExecutor.kt b/app/src/main/java/com/gh/gamecenter/baselist/ListExecutor.kt index 8d590248aa..c47ee78391 100644 --- a/app/src/main/java/com/gh/gamecenter/baselist/ListExecutor.kt +++ b/app/src/main/java/com/gh/gamecenter/baselist/ListExecutor.kt @@ -1,5 +1,6 @@ package com.gh.gamecenter.baselist +import com.gh.base.GHThreadFactory import com.gh.common.AppExecutor import java.util.concurrent.Executors @@ -9,6 +10,6 @@ object ListExecutor { val uiExecutor = AppExecutor.uiExecutor @JvmStatic - val workerExecutor by lazy { Executors.newSingleThreadExecutor() } + val workerExecutor by lazy { Executors.newSingleThreadExecutor(GHThreadFactory("GH_LIST_COMPARATOR_THREAD")) } } \ No newline at end of file diff --git a/app/src/main/java/com/gh/gamecenter/mygame/MyPlayedGameFragment.kt b/app/src/main/java/com/gh/gamecenter/mygame/MyPlayedGameFragment.kt index d22d7fed4a..62ba1b0819 100644 --- a/app/src/main/java/com/gh/gamecenter/mygame/MyPlayedGameFragment.kt +++ b/app/src/main/java/com/gh/gamecenter/mygame/MyPlayedGameFragment.kt @@ -5,6 +5,7 @@ import android.os.Build import android.os.Bundle import com.gh.base.BaseActivity_TabLayout import com.gh.common.constant.Constants +import com.gh.common.runOnIoThread import com.gh.common.util.SPUtils import com.gh.common.util.UsageStatsHelper import com.gh.download.DownloadManager @@ -27,7 +28,9 @@ class MyPlayedGameFragment : PlayedGameFragment() { super.onCreate(savedInstanceState) // 提交用户使用数据 - UsageStatsHelper.checkAndPostUsageStats() + runOnIoThread { + UsageStatsHelper.checkAndPostUsageStats() + } } override fun provideListAdapter(): ListAdapter { diff --git a/app/src/main/java/com/gh/gamecenter/retrofit/RetrofitManager.java b/app/src/main/java/com/gh/gamecenter/retrofit/RetrofitManager.java index 0e6ae66d09..031290071e 100644 --- a/app/src/main/java/com/gh/gamecenter/retrofit/RetrofitManager.java +++ b/app/src/main/java/com/gh/gamecenter/retrofit/RetrofitManager.java @@ -45,7 +45,7 @@ public class RetrofitManager { OkHttpClient okHttpNormalConfig = getOkHttpConfig(context, NORMAL_CONN_TIME_OUT, NORMAL_READ_TIME_OUT); mApiService = provideService(okHttpNormalConfig, Config.API_HOST, ApiService.class); mUploadApiService = provideService(getOkHttpConfig(context, UPLOAD_TIME_OUT, UPLOAD_TIME_OUT), Config.API_HOST, ApiService.class); - mSensitiveApiService = provideService(getOkHttpConfig(context, UPLOAD_TIME_OUT, UPLOAD_TIME_OUT), Config.SENSITIVE_API_HOST, ApiService.class); + mSensitiveApiService = mApiService; } private OkHttpClient getOkHttpConfig(Context context, int connTimeout, int readTimeout) { diff --git a/app/src/main/java/com/halo/assistant/HaloApp.java b/app/src/main/java/com/halo/assistant/HaloApp.java index bca94d3e9c..8e746ff631 100644 --- a/app/src/main/java/com/halo/assistant/HaloApp.java +++ b/app/src/main/java/com/halo/assistant/HaloApp.java @@ -149,6 +149,8 @@ public class HaloApp extends MultiDexApplication { mChannel = Config.DEFAULT_CHANNEL; } + RxJavaPlugins.setIoSchedulerHandler(scheduler -> AppExecutor.INSTANCE.getCachedScheduler()); + if (isUserAcceptPrivacyPolicy(this)) { initPushSdk(); postInit(); @@ -231,9 +233,9 @@ public class HaloApp extends MultiDexApplication { } private void initDataHelper() { - ExposureManager.init(); - LoghubUtils.init(this); - VideoRecordUtils.init(this); + ExposureManager.init(AppExecutor.getLogExecutor()); + LoghubUtils.init(this, AppExecutor.getLogExecutor()); + VideoRecordUtils.init(this, AppExecutor.getLogExecutor()); } // todo 动态注册和静态注册并行的话会触发多次回调