Use ThreadPoolExecutor for spider worker

This commit is contained in:
seven332 committed 2016-03-29 13:35:54 +08:00
1 parent cddb51b399
commit 325cf311df
1 file changed
+28 -47
@@ -49,6 +49,7 @@ import com.hippo.ehviewer.gallery.gl.GalleryPageView;
import com.hippo.image.Image;
import com.hippo.unifile.UniFile;
import com.hippo.yorozuya.IOUtils;
import com.hippo.yorozuya.MathUtils;
import com.hippo.yorozuya.OSUtils;
import com.hippo.yorozuya.PriorityThread;
import com.hippo.yorozuya.PriorityThreadFactory;
@@ -71,7 +72,9 @@ import java.util.Queue;
import java.util.Stack;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.LinkedBlockingDeque;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import okhttp3.Call;
@@ -84,7 +87,7 @@ public class SpiderQueen implements Runnable {
private static final String TAG = SpiderQueen.class.getSimpleName();
private static final AtomicInteger sIdGenerator = new AtomicInteger();
private static final boolean DEBUG_LOG = false;
private static final boolean DEBUG_LOG = true;
@IntDef({MODE_READ, MODE_DOWNLOAD})
@Retention(RetentionPolicy.SOURCE)
@@ -129,16 +132,15 @@ public class SpiderQueen implements Runnable {
@Nullable
private volatile Thread mQueenThread;
private final Object mQueenLock = new Object();
private final ThreadFactory mThreadFactory = new PriorityThreadFactory(
SpiderWorker.class.getSimpleName(), Process.THREAD_PRIORITY_BACKGROUND);
@Nullable
private Thread mDecoderThread;
private final Stack<Integer> mDecodeRequestStack = new Stack<>();
private final AtomicInteger mDecodingIndex = new AtomicInteger(GalleryPageView.INVALID_INDEX);
private volatile Thread[] mWorkers;
private final Object mWorkerLock = new Object();
private ThreadPoolExecutor mWorkerPoolExecutor;
private int mWorkerCount;
private final Object mPTokenLock = new Object();
private volatile SpiderInfo mSpiderInfo;
@@ -166,7 +168,7 @@ public class SpiderQueen implements Runnable {
private final List<OnSpiderListener> mSpiderListeners = new ArrayList<>();
private final int mSpiderWorkerNumber;
private final int mWorkerMaxCount;
private final int mPreloadNumber;
private SpiderQueen(EhApplication application, @NonNull GalleryInfo galleryInfo) {
@@ -175,8 +177,12 @@ public class SpiderQueen implements Runnable {
mGalleryInfo = galleryInfo;
mSpiderDen = new SpiderDen(mGalleryInfo);
mSpiderWorkerNumber = Settings.getMultiThreadDownload();
mPreloadNumber = Settings.getPreloadImage();
mWorkerMaxCount = MathUtils.clamp(Settings.getMultiThreadDownload(), 1, 10);
mPreloadNumber = MathUtils.clamp(Settings.getPreloadImage(), 0, 100);
mWorkerPoolExecutor = new ThreadPoolExecutor(mWorkerMaxCount, mWorkerMaxCount,
0, TimeUnit.SECONDS, new LinkedBlockingDeque<Runnable>(),
new PriorityThreadFactory(SpiderWorker.class.getSimpleName(), Process.THREAD_PRIORITY_BACKGROUND));
}
public void addOnSpiderListener(OnSpiderListener listener) {
@@ -541,17 +547,13 @@ public class SpiderQueen implements Runnable {
private void ensureWorkers() {
synchronized (mWorkerLock) {
if (mWorkers == null) {
mWorkers = new Thread[mSpiderWorkerNumber];
if (null == mWorkerPoolExecutor) {
Log.e(TAG, "Try to start worker after stopped");
return;
}
for (int i = 0, n = mWorkers.length; i < n; i++) {
if (mWorkers[i] == null) {
SpiderWorker worker = new SpiderWorker(i);
Thread thread = mThreadFactory.newThread(worker);
mWorkers[i] = thread;
thread.start();
}
for (; mWorkerCount < mWorkerMaxCount; mWorkerCount++) {
mWorkerPoolExecutor.execute(new SpiderWorker());
}
}
}
@@ -887,18 +889,9 @@ public class SpiderQueen implements Runnable {
// Interrupt all workers
synchronized (mWorkerLock) {
if (mWorkers != null) {
for (int i = 0, n = mWorkers.length; i < n; i++) {
Thread thread = mWorkers[i];
if (thread != null) {
thread.interrupt();
mWorkers[i] = null;
}
}
mWorkers = null;
}
mWorkerPoolExecutor.shutdownNow();
mWorkerPoolExecutor = null;
}
notifyFinish();
if (DEBUG_LOG) {
@@ -908,11 +901,9 @@ public class SpiderQueen implements Runnable {
private class SpiderWorker implements Runnable {
private final int mWorkerIndex;
private final long mGid;
public SpiderWorker(int workerIndex) {
mWorkerIndex = workerIndex;
public SpiderWorker() {
mGid = mGalleryInfo.gid;
}
@@ -1242,25 +1233,15 @@ public class SpiderQueen implements Runnable {
while (!Thread.currentThread().isInterrupted() && runInternal());
boolean finish = true;
boolean finish;
// Clear in spider worker array
synchronized (mWorkerLock) {
if (mWorkers != null && mWorkerIndex < mWorkers.length &&
mWorkers[mWorkerIndex] == Thread.currentThread()) {
mWorkers[mWorkerIndex] = null;
}
if (mWorkers != null) {
for (Thread mWorker : mWorkers) {
if (null != mWorker) {
finish = false;
break;
}
}
}
if (finish) {
mWorkers = null;
mWorkerCount--;
if (mWorkerCount < 0) {
Log.e(TAG, "WTF, mWorkerCount < 0, not thread safe or something wrong");
mWorkerCount = 0;
}
finish = mWorkerCount <= 0;
}
if (finish) {