From 3904406d742ebb7b303a1ff25fd9099625062bd7 Mon Sep 17 00:00:00 2001 From: seven332 Date: Sat, 19 Jan 2019 14:05:33 +0800 Subject: [PATCH] Add IoThreadPoolExecutor --- .../com/hippo/ehviewer/EhApplication.java | 3 +- .../com/hippo/ehviewer/client/EhClient.java | 13 +-- .../ehviewer/download/DownloadManager.java | 3 +- .../ehviewer/preference/TaskPreference.java | 3 +- .../hippo/ehviewer/spider/SpiderQueen.java | 3 +- .../hippo/ehviewer/ui/CommonOperations.java | 3 +- .../ehviewer/ui/scene/DownloadsScene.java | 3 +- .../com/hippo/util/IoThreadPoolExecutor.java | 90 +++++++++++++++++++ 8 files changed, 104 insertions(+), 17 deletions(-) create mode 100644 app/src/main/java/com/hippo/util/IoThreadPoolExecutor.java diff --git a/app/src/main/java/com/hippo/ehviewer/EhApplication.java b/app/src/main/java/com/hippo/ehviewer/EhApplication.java index c6b5a7f52..64e67ec0b 100644 --- a/app/src/main/java/com/hippo/ehviewer/EhApplication.java +++ b/app/src/main/java/com/hippo/ehviewer/EhApplication.java @@ -52,6 +52,7 @@ import com.hippo.text.Html; import com.hippo.unifile.UniFile; import com.hippo.util.BitmapUtils; import com.hippo.util.ExceptionUtils; +import com.hippo.util.IoThreadPoolExecutor; import com.hippo.util.ReadableTime; import com.hippo.yorozuya.FileUtils; import com.hippo.yorozuya.IntIdGenerator; @@ -142,7 +143,7 @@ public class EhApplication extends RecordingApplication { return null; } - }.doInBackground(); + }.executeOnExecutor(IoThreadPoolExecutor.getInstance()); // Check app update update(); diff --git a/app/src/main/java/com/hippo/ehviewer/client/EhClient.java b/app/src/main/java/com/hippo/ehviewer/client/EhClient.java index cd6c506ed..1f4d47149 100644 --- a/app/src/main/java/com/hippo/ehviewer/client/EhClient.java +++ b/app/src/main/java/com/hippo/ehviewer/client/EhClient.java @@ -22,15 +22,11 @@ import com.hippo.ehviewer.EhApplication; import com.hippo.ehviewer.client.data.GalleryInfo; import com.hippo.ehviewer.client.exception.CancelledException; import com.hippo.util.ExceptionUtils; +import com.hippo.util.IoThreadPoolExecutor; import com.hippo.yorozuya.SimpleHandler; -import com.hippo.yorozuya.thread.PriorityThreadFactory; import java.io.File; import java.util.List; -import java.util.concurrent.BlockingQueue; -import java.util.concurrent.LinkedBlockingQueue; -import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadPoolExecutor; -import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicReference; import okhttp3.Call; @@ -64,12 +60,7 @@ public class EhClient { private final OkHttpClient mOkHttpClient; public EhClient(Context context) { - int poolSize = 3; - BlockingQueue requestWorkQueue = new LinkedBlockingQueue<>(); - ThreadFactory threadFactory = new PriorityThreadFactory(TAG, - android.os.Process.THREAD_PRIORITY_BACKGROUND); - mRequestThreadPool = new ThreadPoolExecutor(poolSize, poolSize, - 1L, TimeUnit.SECONDS, requestWorkQueue, threadFactory); + mRequestThreadPool = IoThreadPoolExecutor.getInstance(); mOkHttpClient = EhApplication.getOkHttpClient(context); } diff --git a/app/src/main/java/com/hippo/ehviewer/download/DownloadManager.java b/app/src/main/java/com/hippo/ehviewer/download/DownloadManager.java index 2f259a283..40c28ea90 100644 --- a/app/src/main/java/com/hippo/ehviewer/download/DownloadManager.java +++ b/app/src/main/java/com/hippo/ehviewer/download/DownloadManager.java @@ -32,6 +32,7 @@ import com.hippo.ehviewer.spider.SpiderInfo; import com.hippo.ehviewer.spider.SpiderQueen; import com.hippo.image.Image; import com.hippo.unifile.UniFile; +import com.hippo.util.IoThreadPoolExecutor; import com.hippo.yorozuya.ConcurrentPool; import com.hippo.yorozuya.MathUtils; import com.hippo.yorozuya.ObjectUtils; @@ -611,7 +612,7 @@ public class DownloadManager implements SpiderQueen.OnSpiderListener { } return null; } - }.execute(); + }.executeOnExecutor(IoThreadPoolExecutor.getInstance()); } // Update in DB diff --git a/app/src/main/java/com/hippo/ehviewer/preference/TaskPreference.java b/app/src/main/java/com/hippo/ehviewer/preference/TaskPreference.java index 7891394aa..0969dd09f 100644 --- a/app/src/main/java/com/hippo/ehviewer/preference/TaskPreference.java +++ b/app/src/main/java/com/hippo/ehviewer/preference/TaskPreference.java @@ -30,6 +30,7 @@ import android.util.AttributeSet; import com.hippo.ehviewer.EhApplication; import com.hippo.ehviewer.R; import com.hippo.preference.DialogPreference; +import com.hippo.util.IoThreadPoolExecutor; import com.hippo.yorozuya.IntIdGenerator; public abstract class TaskPreference extends DialogPreference { @@ -62,7 +63,7 @@ public abstract class TaskPreference extends DialogPreference { mTask = onCreateTask(); mTask.setPreference(this); mTaskId = ((EhApplication) getContext().getApplicationContext()).putGlobalStuff(mTask); - mTask.execute(); + mTask.executeOnExecutor(IoThreadPoolExecutor.getInstance()); } } diff --git a/app/src/main/java/com/hippo/ehviewer/spider/SpiderQueen.java b/app/src/main/java/com/hippo/ehviewer/spider/SpiderQueen.java index 2866938f7..183744bb3 100644 --- a/app/src/main/java/com/hippo/ehviewer/spider/SpiderQueen.java +++ b/app/src/main/java/com/hippo/ehviewer/spider/SpiderQueen.java @@ -53,6 +53,7 @@ import com.hippo.streampipe.InputStreamPipe; import com.hippo.streampipe.OutputStreamPipe; import com.hippo.unifile.UniFile; import com.hippo.util.ExceptionUtils; +import com.hippo.util.IoThreadPoolExecutor; import com.hippo.yorozuya.IOUtils; import com.hippo.yorozuya.MathUtils; import com.hippo.yorozuya.OSUtils; @@ -669,7 +670,7 @@ public final class SpiderQueen implements Runnable { writeSpiderInfoToLocal(spiderInfo); return null; } - }.execute(); + }.executeOnExecutor(IoThreadPoolExecutor.getInstance()); } } diff --git a/app/src/main/java/com/hippo/ehviewer/ui/CommonOperations.java b/app/src/main/java/com/hippo/ehviewer/ui/CommonOperations.java index 478be560a..627ec33fa 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/CommonOperations.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/CommonOperations.java @@ -42,6 +42,7 @@ import com.hippo.ehviewer.ui.scene.BaseScene; import com.hippo.text.Html; import com.hippo.unifile.UniFile; import com.hippo.util.ExceptionUtils; +import com.hippo.util.IoThreadPoolExecutor; import com.hippo.yorozuya.FileUtils; import com.hippo.yorozuya.IOUtils; @@ -68,7 +69,7 @@ public final class CommonOperations { public static void checkUpdate(Activity activity, boolean feedback) { if (!UPDATING) { UPDATING = true; - new UpdateTask(activity, feedback).execute(); + new UpdateTask(activity, feedback).executeOnExecutor(IoThreadPoolExecutor.getInstance()); } } diff --git a/app/src/main/java/com/hippo/ehviewer/ui/scene/DownloadsScene.java b/app/src/main/java/com/hippo/ehviewer/ui/scene/DownloadsScene.java index a0a8f5459..32645c665 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/scene/DownloadsScene.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/scene/DownloadsScene.java @@ -84,6 +84,7 @@ import com.hippo.streampipe.InputStreamPipe; import com.hippo.unifile.UniFile; import com.hippo.util.ApiHelper; import com.hippo.util.DrawableManager; +import com.hippo.util.IoThreadPoolExecutor; import com.hippo.view.ViewTransition; import com.hippo.widget.FabLayout; import com.hippo.widget.LoadImageView; @@ -935,7 +936,7 @@ public class DownloadsScene extends ToolbarScene } return null; } - }.execute(files); + }.executeOnExecutor(IoThreadPoolExecutor.getInstance(), files); } private class DeleteDialogHelper implements DialogInterface.OnClickListener { diff --git a/app/src/main/java/com/hippo/util/IoThreadPoolExecutor.java b/app/src/main/java/com/hippo/util/IoThreadPoolExecutor.java new file mode 100644 index 000000000..723d5da76 --- /dev/null +++ b/app/src/main/java/com/hippo/util/IoThreadPoolExecutor.java @@ -0,0 +1,90 @@ +/* + * Copyright 2019 Hippo Seven + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.hippo.util; + +import android.support.annotation.NonNull; +import com.hippo.yorozuya.thread.PriorityThreadFactory; +import java.util.concurrent.BlockingQueue; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.RejectedExecutionHandler; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class IoThreadPoolExecutor extends ThreadPoolExecutor { + + private final static ThreadPoolExecutor INSTANCE = + IoThreadPoolExecutor.newInstance(3, 32, 1L, TimeUnit.SECONDS, + new PriorityThreadFactory("IO",android.os.Process.THREAD_PRIORITY_BACKGROUND)); + + private IoThreadPoolExecutor( + int corePoolSize, + int maximumPoolSize, + long keepAliveTime, + TimeUnit unit, + BlockingQueue workQueue, + ThreadFactory threadFactory, + RejectedExecutionHandler handler + ) { + super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler); + } + + public static ThreadPoolExecutor getInstance() { + return INSTANCE; + } + + private static ThreadPoolExecutor newInstance( + int corePoolSize, + int maximumPoolSize, + long keepAliveTime, + TimeUnit unit, + ThreadFactory threadFactory + ) { + ThreadQueue queue = new ThreadQueue(); + PutRunnableBackHandler handler = new PutRunnableBackHandler(); + IoThreadPoolExecutor executor = new IoThreadPoolExecutor( + corePoolSize, maximumPoolSize, keepAliveTime, unit, queue, threadFactory, handler); + queue.setThreadPoolExecutor(executor); + return executor; + } + + private static class ThreadQueue extends LinkedBlockingQueue { + + private ThreadPoolExecutor executor; + + void setThreadPoolExecutor(ThreadPoolExecutor executor) { + this.executor = executor; + } + + @Override + public boolean offer(@NonNull Runnable o) { + int allWorkingThreads = executor.getActiveCount() + super.size(); + return allWorkingThreads < executor.getPoolSize() && super.offer(o); + } + } + + public static class PutRunnableBackHandler implements RejectedExecutionHandler { + public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { + try { + executor.getQueue().put(r); + } catch (InterruptedException e) { + throw new RejectedExecutionException(e); + } + } + } +}