Index: /trunk/src/org/openstreetmap/josm/data/cache/HostLimitQueue.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/cache/HostLimitQueue.java	(revision 11437)
+++ /trunk/src/org/openstreetmap/josm/data/cache/HostLimitQueue.java	(revision 11438)
@@ -9,4 +9,5 @@
 import java.util.concurrent.LinkedBlockingDeque;
 import java.util.concurrent.Semaphore;
+import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
@@ -32,4 +33,10 @@
     private final Map<String, Semaphore> hostSemaphores = new ConcurrentHashMap<>();
     private final int hostLimit;
+
+    private ThreadPoolExecutor executor;
+
+    private int corePoolSize;
+
+    private int maximumPoolSize;
 
     /**
@@ -93,4 +100,39 @@
     }
 
+    /**
+     * Set the executor for which this queue works. It's needed to spawn new threads.
+     * See: http://stackoverflow.com/questions/9622599/java-threadpoolexecutor-strategy-direct-handoff-with-queue#
+     *
+     * @param executor
+     */
+
+    public void setExecutor(ThreadPoolExecutor executor) {
+        this.executor = executor;
+        this.maximumPoolSize = executor.getMaximumPoolSize();
+        this.corePoolSize = executor.getCorePoolSize();
+    }
+
+    @Override
+    public boolean offer(Runnable e)
+    {
+        if (super.offer(e) == false)
+        {
+            return false;
+        }
+
+        if (executor != null) {
+            // See: http://stackoverflow.com/questions/9622599/java-threadpoolexecutor-strategy-direct-handoff-with-queue#
+            // force spawn of a thread if not reached maximum
+            int currentPoolSize = executor.getPoolSize();
+            if (currentPoolSize < maximumPoolSize
+                    && currentPoolSize >= corePoolSize)
+            {
+                executor.setCorePoolSize(currentPoolSize + 1);
+                executor.setCorePoolSize(corePoolSize);
+            }
+        }
+        return true;
+    }
+
     private Semaphore getSemaphore(JCSCachedTileLoaderJob<?, ?> job) {
         String host;
Index: /trunk/src/org/openstreetmap/josm/data/imagery/TMSCachedTileLoader.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/imagery/TMSCachedTileLoader.java	(revision 11437)
+++ /trunk/src/org/openstreetmap/josm/data/imagery/TMSCachedTileLoader.java	(revision 11438)
@@ -78,12 +78,15 @@
      */
     public static ThreadPoolExecutor getNewThreadPoolExecutor(String nameFormat, int workers) {
-        return new ThreadPoolExecutor(
-                workers, // keep the thread number constant
+        HostLimitQueue workQueue = new HostLimitQueue(HOST_LIMIT.get().intValue());
+        ThreadPoolExecutor executor = new ThreadPoolExecutor(
+                0, // 0 so for unused thread pools threads will eventually die, freeing also the threadpool
                 workers, // do not this number of threads
-                30, // keepalive for thread
+                300, // keepalive for thread
                 TimeUnit.SECONDS,
-                new HostLimitQueue(HOST_LIMIT.get().intValue()),
+                workQueue,
                 Utils.newThreadFactory(nameFormat, Thread.NORM_PRIORITY)
                 );
+        workQueue.setExecutor(executor);
+        return executor;
     }
 
Index: /trunk/src/org/openstreetmap/josm/data/imagery/WMSCachedTileLoader.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/imagery/WMSCachedTileLoader.java	(revision 11437)
+++ /trunk/src/org/openstreetmap/josm/data/imagery/WMSCachedTileLoader.java	(revision 11438)
@@ -10,4 +10,5 @@
 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener;
 import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry;
+import org.openstreetmap.josm.data.preferences.IntegerProperty;
 
 /**
@@ -20,4 +21,8 @@
 public class WMSCachedTileLoader extends TMSCachedTileLoader {
 
+    /**
+     * overrides the THREAD_LIMIT in superclass, as we want to have separate limit and pool for WMS
+     */
+    public static final IntegerProperty THREAD_LIMIT = new IntegerProperty("imagery.wms.loader.maxjobs", 3);
     /**
      * Creates a TileLoader with separate WMS downloader.
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/imagery/WMSSettingsPanel.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/imagery/WMSSettingsPanel.java	(revision 11437)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/imagery/WMSSettingsPanel.java	(revision 11438)
@@ -13,5 +13,5 @@
 import javax.swing.SpinnerNumberModel;
 
-import org.openstreetmap.josm.data.imagery.WMSCachedTileLoaderJob;
+import org.openstreetmap.josm.data.imagery.WMSCachedTileLoader;
 import org.openstreetmap.josm.gui.layer.WMSLayer;
 import org.openstreetmap.josm.tools.GBC;
@@ -49,5 +49,5 @@
         add(Box.createHorizontalGlue(), GBC.eol().fill(GBC.HORIZONTAL));
         JLabel labelSimConn = new JLabel(tr("Simultaneous connections:"));
-        int threadLimitValue = Utils.clamp(WMSCachedTileLoaderJob.THREAD_LIMIT.get(), THREADS_MIN, THREADS_MAX);
+        int threadLimitValue = Utils.clamp(WMSCachedTileLoader.THREAD_LIMIT.get(), THREADS_MIN, THREADS_MAX);
         spinSimConn = new JSpinner(new SpinnerNumberModel(threadLimitValue, THREADS_MIN, THREADS_MAX, 1));
         labelSimConn.setLabelFor(spinSimConn);
@@ -71,5 +71,5 @@
     public void loadSettings() {
         this.autozoomActive.setSelected(WMSLayer.PROP_DEFAULT_AUTOZOOM.get());
-        this.spinSimConn.setValue(WMSCachedTileLoaderJob.THREAD_LIMIT.get());
+        this.spinSimConn.setValue(WMSCachedTileLoader.THREAD_LIMIT.get());
         this.tileSize.setValue(WMSLayer.PROP_IMAGE_SIZE.get());
     }
@@ -81,5 +81,5 @@
     public boolean saveSettings() {
         WMSLayer.PROP_DEFAULT_AUTOZOOM.put(this.autozoomActive.isSelected());
-        WMSCachedTileLoaderJob.THREAD_LIMIT.put((Integer) spinSimConn.getModel().getValue());
+        WMSCachedTileLoader.THREAD_LIMIT.put((Integer) spinSimConn.getModel().getValue());
         WMSLayer.PROP_IMAGE_SIZE.put((Integer) this.tileSize.getModel().getValue());
 
