Changeset 11438 in josm


Ignore:
Timestamp:
2017-01-07T09:44:59+01:00 (2 years ago)
Author:
wiktorn
Message:

Fix thread pool for WMS

Because threds in WMS download ThreadPool never died, the unreferenced ThreadPool object (and its threads) was never cleared. To fix this minimum size of ThreadPool was changed to 0.

But due to the fact, that ThreadPoolExecutor spawns new Thread only when workQueue refuses to take a new job, workaround is implemented in HostLimitQueue based on: http://stackoverflow.com/questions/9622599/java-threadpoolexecutor-strategy-direct-handoff-with-queue#

WMS Settings was fixed so now WMS has it's own THREAD_LIMIT setting not connected to JCS default setting.

Location:
trunk/src/org/openstreetmap/josm
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/data/cache/HostLimitQueue.java

    r11381 r11438  
    99import java.util.concurrent.LinkedBlockingDeque;
    1010import java.util.concurrent.Semaphore;
     11import java.util.concurrent.ThreadPoolExecutor;
    1112import java.util.concurrent.TimeUnit;
    1213
     
    3233    private final Map<String, Semaphore> hostSemaphores = new ConcurrentHashMap<>();
    3334    private final int hostLimit;
     35
     36    private ThreadPoolExecutor executor;
     37
     38    private int corePoolSize;
     39
     40    private int maximumPoolSize;
    3441
    3542    /**
     
    93100    }
    94101
     102    /**
     103     * Set the executor for which this queue works. It's needed to spawn new threads.
     104     * See: http://stackoverflow.com/questions/9622599/java-threadpoolexecutor-strategy-direct-handoff-with-queue#
     105     *
     106     * @param executor
     107     */
     108
     109    public void setExecutor(ThreadPoolExecutor executor) {
     110        this.executor = executor;
     111        this.maximumPoolSize = executor.getMaximumPoolSize();
     112        this.corePoolSize = executor.getCorePoolSize();
     113    }
     114
     115    @Override
     116    public boolean offer(Runnable e)
     117    {
     118        if (super.offer(e) == false)
     119        {
     120            return false;
     121        }
     122
     123        if (executor != null) {
     124            // See: http://stackoverflow.com/questions/9622599/java-threadpoolexecutor-strategy-direct-handoff-with-queue#
     125            // force spawn of a thread if not reached maximum
     126            int currentPoolSize = executor.getPoolSize();
     127            if (currentPoolSize < maximumPoolSize
     128                    && currentPoolSize >= corePoolSize)
     129            {
     130                executor.setCorePoolSize(currentPoolSize + 1);
     131                executor.setCorePoolSize(corePoolSize);
     132            }
     133        }
     134        return true;
     135    }
     136
    95137    private Semaphore getSemaphore(JCSCachedTileLoaderJob<?, ?> job) {
    96138        String host;
  • trunk/src/org/openstreetmap/josm/data/imagery/TMSCachedTileLoader.java

    r10877 r11438  
    7878     */
    7979    public static ThreadPoolExecutor getNewThreadPoolExecutor(String nameFormat, int workers) {
    80         return new ThreadPoolExecutor(
    81                 workers, // keep the thread number constant
     80        HostLimitQueue workQueue = new HostLimitQueue(HOST_LIMIT.get().intValue());
     81        ThreadPoolExecutor executor = new ThreadPoolExecutor(
     82                0, // 0 so for unused thread pools threads will eventually die, freeing also the threadpool
    8283                workers, // do not this number of threads
    83                 30, // keepalive for thread
     84                300, // keepalive for thread
    8485                TimeUnit.SECONDS,
    85                 new HostLimitQueue(HOST_LIMIT.get().intValue()),
     86                workQueue,
    8687                Utils.newThreadFactory(nameFormat, Thread.NORM_PRIORITY)
    8788                );
     89        workQueue.setExecutor(executor);
     90        return executor;
    8891    }
    8992
  • trunk/src/org/openstreetmap/josm/data/imagery/WMSCachedTileLoader.java

    r8734 r11438  
    1010import org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener;
    1111import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry;
     12import org.openstreetmap.josm.data.preferences.IntegerProperty;
    1213
    1314/**
     
    2021public class WMSCachedTileLoader extends TMSCachedTileLoader {
    2122
     23    /**
     24     * overrides the THREAD_LIMIT in superclass, as we want to have separate limit and pool for WMS
     25     */
     26    public static final IntegerProperty THREAD_LIMIT = new IntegerProperty("imagery.wms.loader.maxjobs", 3);
    2227    /**
    2328     * Creates a TileLoader with separate WMS downloader.
  • trunk/src/org/openstreetmap/josm/gui/preferences/imagery/WMSSettingsPanel.java

    r11287 r11438  
    1313import javax.swing.SpinnerNumberModel;
    1414
    15 import org.openstreetmap.josm.data.imagery.WMSCachedTileLoaderJob;
     15import org.openstreetmap.josm.data.imagery.WMSCachedTileLoader;
    1616import org.openstreetmap.josm.gui.layer.WMSLayer;
    1717import org.openstreetmap.josm.tools.GBC;
     
    4949        add(Box.createHorizontalGlue(), GBC.eol().fill(GBC.HORIZONTAL));
    5050        JLabel labelSimConn = new JLabel(tr("Simultaneous connections:"));
    51         int threadLimitValue = Utils.clamp(WMSCachedTileLoaderJob.THREAD_LIMIT.get(), THREADS_MIN, THREADS_MAX);
     51        int threadLimitValue = Utils.clamp(WMSCachedTileLoader.THREAD_LIMIT.get(), THREADS_MIN, THREADS_MAX);
    5252        spinSimConn = new JSpinner(new SpinnerNumberModel(threadLimitValue, THREADS_MIN, THREADS_MAX, 1));
    5353        labelSimConn.setLabelFor(spinSimConn);
     
    7171    public void loadSettings() {
    7272        this.autozoomActive.setSelected(WMSLayer.PROP_DEFAULT_AUTOZOOM.get());
    73         this.spinSimConn.setValue(WMSCachedTileLoaderJob.THREAD_LIMIT.get());
     73        this.spinSimConn.setValue(WMSCachedTileLoader.THREAD_LIMIT.get());
    7474        this.tileSize.setValue(WMSLayer.PROP_IMAGE_SIZE.get());
    7575    }
     
    8181    public boolean saveSettings() {
    8282        WMSLayer.PROP_DEFAULT_AUTOZOOM.put(this.autozoomActive.isSelected());
    83         WMSCachedTileLoaderJob.THREAD_LIMIT.put((Integer) spinSimConn.getModel().getValue());
     83        WMSCachedTileLoader.THREAD_LIMIT.put((Integer) spinSimConn.getModel().getValue());
    8484        WMSLayer.PROP_IMAGE_SIZE.put((Integer) this.tileSize.getModel().getValue());
    8585
Note: See TracChangeset for help on using the changeset viewer.