From 24d0e97c341f71264bab5aa51916d2b98677d270 Mon Sep 17 00:00:00 2001 From: Sergej Orlov Date: Sun, 2 Feb 2020 16:19:56 +0100 Subject: [PATCH] http server: do not terminate old thread when threads limit reached Original implementation of the thread pool was limiting max number of threads by terminating oldest thread if the limit was already reached and a new request has arrived. This was causing broken responses under load. Instead we now wait until one of the threads completes before starting a new one. --- .../main/java/btools/server/RouteServer.java | 46 +++---------------- 1 file changed, 6 insertions(+), 40 deletions(-) diff --git a/brouter-server/src/main/java/btools/server/RouteServer.java b/brouter-server/src/main/java/btools/server/RouteServer.java index 57689a4..14632f0 100644 --- a/brouter-server/src/main/java/btools/server/RouteServer.java +++ b/brouter-server/src/main/java/btools/server/RouteServer.java @@ -15,6 +15,7 @@ import java.net.Socket; import java.net.URLDecoder; import java.text.DateFormat; import java.text.SimpleDateFormat; +import java.util.concurrent.Semaphore; import java.util.Date; import java.util.HashMap; import java.util.List; @@ -46,14 +47,8 @@ public class RouteServer extends Thread private Socket clientSocket = null; private RoutingEngine cr = null; - private volatile boolean terminated; + private Semaphore semaphore = null; - public void stopRouter() - { - RoutingEngine e = cr; - if ( e != null ) e.terminate(); - } - private static DateFormat tsFormat = new SimpleDateFormat( "dd.MM.yy HH:mm", new Locale( "en", "US" ) ); private static String formattedTimestamp() @@ -270,7 +265,7 @@ public class RouteServer extends Thread if ( br != null ) try { br.close(); } catch( Exception e ) {} if ( bw != null ) try { bw.close(); } catch( Exception e ) {} if ( clientSocket != null ) try { clientSocket.close(); } catch( Exception e ) {} - terminated = true; + semaphore.release(); } } @@ -294,8 +289,7 @@ public class RouteServer extends Thread serviceContext.sharedProfileDir = tk.hasMoreTokens() ? tk.nextToken() : serviceContext.customProfileDir; int maxthreads = Integer.parseInt( args[4] ); - - TreeMap threadMap = new TreeMap(); + Semaphore semaphore = new Semaphore(maxthreads, true); ServerSocket serverSocket = args.length > 5 ? new ServerSocket(Integer.parseInt(args[3]),50,InetAddress.getByName(args[5])) : new ServerSocket(Integer.parseInt(args[3])); @@ -318,36 +312,8 @@ public class RouteServer extends Thread RouteServer server = new RouteServer(); server.serviceContext = serviceContext; server.clientSocket = clientSocket; - - // cleanup thread list - for(;;) - { - boolean removedItem = false; - for (Map.Entry e : threadMap.entrySet()) - { - if ( e.getValue().terminated ) - { - threadMap.remove( e.getKey() ); - removedItem = true; - break; - } - } - if ( !removedItem ) break; - } - - // kill thread if limit reached - if ( threadMap.size() >= maxthreads ) - { - Long k = threadMap.firstKey(); - RouteServer victim = threadMap.get( k ); - threadMap.remove( k ); - victim.stopRouter(); - } - - long ts = System.currentTimeMillis(); - while ( ts <= last_ts ) ts++; - threadMap.put( Long.valueOf( ts ), server ); - last_ts = ts; + server.semaphore = semaphore; + semaphore.acquire(); server.start(); } }