diff --git a/OsmAnd/src/net/osmand/plus/routing/VoiceRouter.java b/OsmAnd/src/net/osmand/plus/routing/VoiceRouter.java index 43aaff0668..6290baa66c 100644 --- a/OsmAnd/src/net/osmand/plus/routing/VoiceRouter.java +++ b/OsmAnd/src/net/osmand/plus/routing/VoiceRouter.java @@ -901,7 +901,7 @@ public class VoiceRouter { } else if (type == ROUTE_RECALCULATED) { newCommand.routeRecalculated(left, time); } - VoiceRouter.play(newCommand); + VoiceRouter.this.play(newCommand); } } } diff --git a/OsmAnd/src/net/osmand/plus/views/Renderable.java b/OsmAnd/src/net/osmand/plus/views/Renderable.java index c4581c329e..a07e44cc57 100644 --- a/OsmAnd/src/net/osmand/plus/views/Renderable.java +++ b/OsmAnd/src/net/osmand/plus/views/Renderable.java @@ -2,6 +2,7 @@ package net.osmand.plus.views; import android.graphics.Canvas; import android.graphics.Paint; +import android.support.annotation.NonNull; import net.osmand.GPXUtilities.WptPt; import net.osmand.data.QuadRect; @@ -9,13 +10,41 @@ import net.osmand.data.RotatedTileBox; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.BlockingQueue; import java.util.concurrent.Executor; -import java.util.concurrent.Executors; +import java.util.concurrent.LinkedBlockingQueue; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; public class Renderable { - private static final Executor THREAD_POOL_EXECUTOR = Executors.newFixedThreadPool(5); + private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); + private static final int CORE_POOL_SIZE = Math.max(2, Math.min(CPU_COUNT - 1, 4)); + private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1; + private static final int KEEP_ALIVE_SECONDS = 30; + + private static final ThreadFactory sThreadFactory = new ThreadFactory() { + private final AtomicInteger mCount = new AtomicInteger(1); + + public Thread newThread(@NonNull Runnable r) { + return new Thread(r, "Renderable #" + mCount.getAndIncrement()); + } + }; + + private static final BlockingQueue sPoolWorkQueue = new LinkedBlockingQueue<>(128); + public static final Executor THREAD_POOL_EXECUTOR; + + static { + ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor( + CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_SECONDS, TimeUnit.SECONDS, + sPoolWorkQueue, sThreadFactory); + threadPoolExecutor.allowCoreThreadTimeOut(true); + THREAD_POOL_EXECUTOR = threadPoolExecutor; + } public static abstract class RenderableSegment { @@ -142,7 +171,11 @@ public class Renderable { double cullDistance = Math.pow(2.0, segmentSize - zoom); // segmentSize == epsilon culler = new AsynchronousResampler.RamerDouglasPeucer(this, cullDistance); - culler.executeOnExecutor(THREAD_POOL_EXECUTOR, ""); + try { + culler.executeOnExecutor(THREAD_POOL_EXECUTOR, ""); + } catch (RejectedExecutionException e) { + culler = null; + } } }