Browse Source

threads now pooled

lookup-tables
Stephan Richter 5 years ago
parent
commit
0dda9f16e0
  1. 2
      pom.xml
  2. 6
      resources/translations/Application.de.translation
  3. 5
      src/main/java/de/srsoftware/web4rail/Application.java
  4. 34
      src/main/java/de/srsoftware/web4rail/ControlUnit.java
  5. 51
      src/main/java/de/srsoftware/web4rail/Plan.java
  6. 19
      src/main/java/de/srsoftware/web4rail/Route.java
  7. 5
      src/main/java/de/srsoftware/web4rail/actions/DelayedAction.java
  8. 5
      src/main/java/de/srsoftware/web4rail/actions/SetContextTrain.java
  9. 5
      src/main/java/de/srsoftware/web4rail/actions/SetDisplayText.java
  10. 5
      src/main/java/de/srsoftware/web4rail/actions/SetRelay.java
  11. 10
      src/main/java/de/srsoftware/web4rail/moving/Train.java
  12. 5
      src/main/java/de/srsoftware/web4rail/tiles/Bridge.java
  13. 7
      src/main/java/de/srsoftware/web4rail/tiles/Contact.java

2
pom.xml

@ -4,7 +4,7 @@ @@ -4,7 +4,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>de.srsoftware</groupId>
<artifactId>web4rail</artifactId>
<version>1.2.63</version>
<version>1.2.64</version>
<name>Web4Rail</name>
<packaging>jar</packaging>
<description>Java Model Railway Control</description>

6
resources/translations/Application.de.translation

@ -103,8 +103,9 @@ Emergency : Notfall @@ -103,8 +103,9 @@ Emergency : Notfall
enable {} : {} aktivieren
export : exportieren
Faster (10 {}) : 10 {} schneller
Firing {} : starte {}
Final speed after breaking, before halting : Endgeschwindigkeit nach Bremsvorgang, vor dem Anhalten
FinishRoute : Route abschließen
Firing {} : starte {}
For each {} do: Für jede(n) {}:
forward : vorwärts
Found {} routes. : {} Routen gefunden.
@ -135,6 +136,7 @@ Locked by {} : Durch {} besetzt @@ -135,6 +136,7 @@ Locked by {} : Durch {} besetzt
Locomotive manager : Lok-Verwaltung
Locomotives\: : Lokomotiven:
Locomotives and cars : Lokomotiven und Waggons
Lower speed limit : Minimale Geschwindigkeit
Manage cars : Waggons verwalten
Manage locos : Lokomotiven verwalten
Manage trains : Züge verwalten
@ -171,7 +173,7 @@ Origin\: {} to {} : Start: {} nach {} @@ -171,7 +173,7 @@ Origin\: {} to {} : Start: {} nach {}
Plan saved as "{}". : Plan als „{}“ gespeichert.
Port for state {} : Anschluss für Status {}
PreserveRoute : Anschlußroute vorwählen
Properties of plan : Plan-Eigenschaften
Properties : Eigenschaften
Properties of {} : Eigenschaften von {}
Properties of {} @ ({},{}) : Eigenschaften von {} @ ({},{})
PushPullTrain : Wendezug

5
src/main/java/de/srsoftware/web4rail/Application.java

@ -15,6 +15,8 @@ import java.net.URLDecoder; @@ -15,6 +15,8 @@ import java.net.URLDecoder;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.util.HashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -40,6 +42,7 @@ import de.srsoftware.web4rail.tiles.Contact; @@ -40,6 +42,7 @@ import de.srsoftware.web4rail.tiles.Contact;
public class Application extends BaseClass{
private static final Logger LOG = LoggerFactory.getLogger(Application.class);
private static final String START_TRAINS = "--start-trains";
public static final ExecutorService threadPool = Executors.newCachedThreadPool();
/**
* entry point for the application:<br/>
@ -63,7 +66,7 @@ public class Application extends BaseClass{ @@ -63,7 +66,7 @@ public class Application extends BaseClass{
server.createContext("/css" , client -> sendFile(client));
server.createContext("/js" , client -> sendFile(client));
server.createContext("/stream", client -> stream(client));
server.setExecutor(java.util.concurrent.Executors.newCachedThreadPool());
server.setExecutor(threadPool);
server.start();
try {
Plan.load(Plan.DEFAULT_NAME);

34
src/main/java/de/srsoftware/web4rail/ControlUnit.java

@ -206,7 +206,7 @@ public class ControlUnit extends Thread implements Constants{ @@ -206,7 +206,7 @@ public class ControlUnit extends Thread implements Constants{
*/
public ControlUnit restart() {
end();
start();
Application.threadPool.execute(this);
return this;
}
@ -215,6 +215,16 @@ public class ControlUnit extends Thread implements Constants{ @@ -215,6 +215,16 @@ public class ControlUnit extends Thread implements Constants{
*/
@Override
public void run() {
try {
handshake(MODE_INFO);
stopped = false;
startInfoThread();
handshake(MODE_COMMAND);
} catch (IOException | TimeoutException e) {
throw new IllegalStateException(e);
}
while (!stopped) {
try {
if (queue.isEmpty()) {
@ -281,23 +291,10 @@ public class ControlUnit extends Thread implements Constants{ @@ -281,23 +291,10 @@ public class ControlUnit extends Thread implements Constants{
return this;
}
@Override
public synchronized void start() {
try {
handshake(MODE_INFO);
stopped = false;
startInfoThread();
handshake(MODE_COMMAND);
} catch (IOException | TimeoutException e) {
throw new IllegalStateException(e);
}
super.start();
}
private void startInfoThread() {
infoSocket = commandSocket; // handshake läuft immer über commandSocket und commandScanner
infoScanner = commandScanner;
new Thread(new Runnable() {
Runnable infoThread = new Runnable() {
@Override
public void run() {
@ -315,12 +312,12 @@ public class ControlUnit extends Thread implements Constants{ @@ -315,12 +312,12 @@ public class ControlUnit extends Thread implements Constants{
case FEEDBACK:
int addr = Integer.parseInt(parts[5]);
boolean active = !parts[6].equals("0");
new Thread() {
Application.threadPool.execute(new Thread() {
@Override
public void run() {
ControlUnit.this.plan.sensor(addr,active);
}
}.start();
});
case ACESSORY:
break;
default:
@ -342,7 +339,8 @@ public class ControlUnit extends Thread implements Constants{ @@ -342,7 +339,8 @@ public class ControlUnit extends Thread implements Constants{
}
}
}).start();
};
Application.threadPool.execute(infoThread);
}
/**

51
src/main/java/de/srsoftware/web4rail/Plan.java

@ -137,6 +137,7 @@ public class Plan extends BaseClass{ @@ -137,6 +137,7 @@ public class Plan extends BaseClass{
private static final String SPEED_UNIT = "speed_unit";
private static final String LENGTH_UNIT = "length_unit";
private static final String CONFIRM = "confirm";
private static final String FINAL_SPEED = "final_speed";
private ControlUnit controlUnit = new ControlUnit(this); // the control unit, to which the plan is connected
private Contact learningContact;
@ -145,7 +146,7 @@ public class Plan extends BaseClass{ @@ -145,7 +146,7 @@ public class Plan extends BaseClass{
* creates a new plan, starts to send heart beats
*/
public Plan() {
new Heartbeat().start();
Application.threadPool.execute(new Heartbeat());
}
/**
@ -269,7 +270,7 @@ public class Plan extends BaseClass{ @@ -269,7 +270,7 @@ public class Plan extends BaseClass{
return win;
}
new Thread() {
Application.threadPool.execute(new Thread() {
public void run() {
Vector<Route> newRoutes = new Vector<Route>();
for (Block block : BaseClass.listElements(Block.class)) {
@ -286,7 +287,7 @@ public class Plan extends BaseClass{ @@ -286,7 +287,7 @@ public class Plan extends BaseClass{
stream(t("Found {} routes.",newRoutes.size()));
}
}.start();
});
return t("Analyzing plan...");
}
@ -308,6 +309,11 @@ public class Plan extends BaseClass{ @@ -308,6 +309,11 @@ public class Plan extends BaseClass{
public ControlUnit controlUnit() {
return controlUnit;
}
public void drop(Tile tile) {
tile.unregister();
stream("remove "+tile.id());
}
/**
* completes a given route during a call to {@link #analyze()}.
@ -427,6 +433,21 @@ public class Plan extends BaseClass{ @@ -427,6 +433,21 @@ public class Plan extends BaseClass{
LOG.debug("learning contact {}",learningContact);
}
public JSONObject json() {
JSONArray jTiles = new JSONArray();
BaseClass.listElements(Tile.class)
.stream()
.filter(tile -> !(tile instanceof Shadow || tile instanceof BlockContact))
.map(tile -> tile.json())
.forEach(jTiles::put);
return new JSONObject()
.put(TILE, jTiles)
.put(SPEED_UNIT, speedUnit)
.put(LENGTH_UNIT, lengthUnit)
.put(FINAL_SPEED, Route.endSpeed);
}
/**
* loads a track layout from a file, along with its assigned cars, trains, routes and control unit settings
* @param filename
@ -453,6 +474,7 @@ public class Plan extends BaseClass{ @@ -453,6 +474,7 @@ public class Plan extends BaseClass{
if (json.has(TILE)) json.getJSONArray(TILE).forEach(object -> Tile.load(object, plan));
if (json.has(LENGTH_UNIT)) lengthUnit = json.getString(LENGTH_UNIT);
if (json.has(SPEED_UNIT)) speedUnit = json.getString(SPEED_UNIT);
if (json.has(FINAL_SPEED)) Route.endSpeed = json.getInt(FINAL_SPEED);
try {
Train.loadAll(filename+".trains",plan);
@ -470,7 +492,7 @@ public class Plan extends BaseClass{ @@ -470,7 +492,7 @@ public class Plan extends BaseClass{
LOG.warn("Was not able to load control unit settings!",e);
}
try {
plan.controlUnit.start();
Application.threadPool.execute(plan.controlUnit);
} catch (Exception e) {
LOG.warn("Was not able to establish connection to control unit!");
}
@ -566,11 +588,6 @@ public class Plan extends BaseClass{ @@ -566,11 +588,6 @@ public class Plan extends BaseClass{
return t(moved ? "Tile(s) moved.":"No tile moved.");
}
public void drop(Tile tile) {
tile.unregister();
stream("remove "+tile.id());
}
/**
* adds a new tile to the plan on the client side
* @param tile
@ -618,6 +635,7 @@ public class Plan extends BaseClass{ @@ -618,6 +635,7 @@ public class Plan extends BaseClass{
new Input(ACTION,ACTION_UPDATE).hideIn(form);
new Input(LENGTH_UNIT, lengthUnit).addTo(new Label(t("Length unit")+":"+NBSP)).addTo(form);
new Input(SPEED_UNIT, speedUnit).addTo(new Label(t("Speed unit")+":"+NBSP)).addTo(form);
new Input(FINAL_SPEED, Route.endSpeed).addTo(new Label(t("Lower speed limit")+":"+NBSP)).attr("title", t("Final speed after breaking, before halting")).addTo(form);
new Button(t("Save"), form).addTo(form);
form.addTo(win);
@ -703,20 +721,6 @@ public class Plan extends BaseClass{ @@ -703,20 +721,6 @@ public class Plan extends BaseClass{
return t("Plan saved as \"{}\".",name);
}
public JSONObject json() {
JSONArray jTiles = new JSONArray();
BaseClass.listElements(Tile.class)
.stream()
.filter(tile -> !(tile instanceof Shadow || tile instanceof BlockContact))
.map(tile -> tile.json())
.forEach(jTiles::put);
return new JSONObject()
.put(TILE, jTiles)
.put(SPEED_UNIT, speedUnit)
.put(LENGTH_UNIT, lengthUnit);
}
public void sensor(int addr, boolean active) {
Contact contact = Contact.get(addr);
@ -857,6 +861,7 @@ public class Plan extends BaseClass{ @@ -857,6 +861,7 @@ public class Plan extends BaseClass{
if (params.containsKey(LENGTH_UNIT)) lengthUnit = params.get(LENGTH_UNIT);
if (params.containsKey(SPEED_UNIT)) speedUnit = params.get(SPEED_UNIT);
if (params.containsKey(FINAL_SPEED)) Route.endSpeed = Integer.parseInt(params.get(FINAL_SPEED));
return t("Plan updated.");

19
src/main/java/de/srsoftware/web4rail/Route.java

@ -69,22 +69,23 @@ public class Route extends BaseClass { @@ -69,22 +69,23 @@ public class Route extends BaseClass {
static final String SIGNALS = "signals";
static final String TURNOUTS = "turnouts";
private State state = State.FREE;
public static int endSpeed = 10;
public static boolean freeBehindTrace = true;
private static final String ROUTE_START = "route_start";
private static final String ROUTE_SETUP = "route_setup";
private static HashMap<Id, String> names = new HashMap<Id, String>(); // maps id to name. needed to keep names during plan.analyze()
private class BrakeProcessor extends Thread {
private int startSpeed;
private static HashMap<Id, String> names = new HashMap<Id, String>(); // maps id to name. needed to keep names during plan.analyze()
private class BrakeProcessor extends Thread {
private long timestamp;
private Integer timeStep;
private Route route;
private Train train;
private boolean aborted = false;
private String brakeId;
private static final int ENDSPEED = 10;
public BrakeProcessor(Route route, Train train) {
this.train = train;
@ -109,7 +110,7 @@ public class Route extends BaseClass { @@ -109,7 +110,7 @@ public class Route extends BaseClass {
//int remainingSpeed = train.speed;
if (aborted) return;
long runtime = timestamp2 - timestamp;
int quotient = startSpeed - ENDSPEED;
int quotient = startSpeed - endSpeed;
if (quotient<1) quotient = 1;
int newTimeStep = 5*(int) runtime/quotient;
@ -128,7 +129,7 @@ public class Route extends BaseClass { @@ -128,7 +129,7 @@ public class Route extends BaseClass {
public void run() {
timestamp = new Date().getTime();
if (train.speed == 0) aborted = true;
while (train.speed > ENDSPEED) {
while (train.speed > endSpeed) {
if (aborted || train.nextRoutePrepared()) break;
train.setSpeed(train.speed - 5);
try {
@ -423,7 +424,9 @@ public class Route extends BaseClass { @@ -423,7 +424,9 @@ public class Route extends BaseClass {
public void finish() {
context.clear(); // prevent delayed actions from firing after route has finished
setSignals(Signal.STOP);
for (Tile tile : path) tile.unset(this);
for (Tile tile : path) try {
tile.unset(this);
} catch (IllegalArgumentException e) {}
Tile lastTile = path.lastElement();
if (lastTile instanceof Contact) {
lastTile.setTrain(null);
@ -439,7 +442,7 @@ public class Route extends BaseClass { @@ -439,7 +442,7 @@ public class Route extends BaseClass {
train.setWaitTime(endBlock.getWaitTime(train,train.direction()));
}
if (train.route == this) train.route = null;
if (!train.onTrace(startBlock)) startBlock.setTrain(null);
if (!train.onTrace(startBlock) && startBlock.train() == train) startBlock.setTrain(null);
}
train = null;
}

5
src/main/java/de/srsoftware/web4rail/actions/DelayedAction.java

@ -6,6 +6,7 @@ import java.util.List; @@ -6,6 +6,7 @@ import java.util.List;
import org.json.JSONObject;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.Window;
import de.srsoftware.web4rail.tags.Fieldset;
@ -27,7 +28,7 @@ public class DelayedAction extends ActionList { @@ -27,7 +28,7 @@ public class DelayedAction extends ActionList {
@Override
public boolean fire(Context context) {
new Thread() {
Application.threadPool.execute(new Thread() {
public void run() {
try {
Thread.sleep(delay);
@ -37,7 +38,7 @@ public class DelayedAction extends ActionList { @@ -37,7 +38,7 @@ public class DelayedAction extends ActionList {
}
DelayedAction.super.fire(context);
};
}.start();
});
return true;
}

5
src/main/java/de/srsoftware/web4rail/actions/SetContextTrain.java

@ -5,6 +5,7 @@ import java.util.List; @@ -5,6 +5,7 @@ import java.util.List;
import org.json.JSONObject;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.Window;
import de.srsoftware.web4rail.moving.Train;
@ -38,14 +39,14 @@ public class SetContextTrain extends Action { @@ -38,14 +39,14 @@ public class SetContextTrain extends Action {
Id trainId = Id.from(json,REALM_TRAIN);
if (isSet(trainId)) {
train = Train.get(trainId);
if (isNull(train)) new Thread() { // load asynchronously, as referred tile may not be available,yet
if (isNull(train)) Application.threadPool.execute(new Thread() { // load asynchronously, as referred tile may not be available,yet
public void run() {
try {
sleep(1000);
train = Train.get(trainId);
} catch (InterruptedException e) {}
};
}.start();
});
}
}
return this;

5
src/main/java/de/srsoftware/web4rail/actions/SetDisplayText.java

@ -5,6 +5,7 @@ import java.util.List; @@ -5,6 +5,7 @@ import java.util.List;
import org.json.JSONObject;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.Window;
import de.srsoftware.web4rail.tags.Fieldset;
@ -39,14 +40,14 @@ public class SetDisplayText extends TextAction{ @@ -39,14 +40,14 @@ public class SetDisplayText extends TextAction{
@Override
public Action load(JSONObject json) {
if (json.has(DISPLAY)) {
new Thread() { // load asynchronously, as referred tile may not be available,yet
Application.threadPool.execute(new Thread() { // load asynchronously, as referred tile may not be available,yet
public void run() {
try {
sleep(1000);
display = (TextDisplay) plan.get(Id.from(json,DISPLAY), false);
} catch (InterruptedException e) {}
};
}.start();
});
}
return super.load(json);
}

5
src/main/java/de/srsoftware/web4rail/actions/SetRelay.java

@ -5,6 +5,7 @@ import java.util.List; @@ -5,6 +5,7 @@ import java.util.List;
import org.json.JSONObject;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.Window;
import de.srsoftware.web4rail.tags.Fieldset;
@ -43,14 +44,14 @@ public class SetRelay extends Action { @@ -43,14 +44,14 @@ public class SetRelay extends Action {
if (json.has(RELAY)) {
String relayId = json.getString(RELAY);
relay = BaseClass.get(new Id(relayId));
if (isNull(relay)) new Thread() { // if relay not loaded, yet: wait one sec and try again
if (isNull(relay)) Application.threadPool.execute(new Thread() { // if relay not loaded, yet: wait one sec and try again
public void run() {
try {
sleep(1000);
} catch (InterruptedException e) {}
relay = BaseClass.get(new Id(relayId));
};
}.start();
});
}
if (json.has(Relay.STATE)) state = json.getBoolean(Relay.STATE);
return this;

10
src/main/java/de/srsoftware/web4rail/moving/Train.java

@ -23,6 +23,7 @@ import org.slf4j.Logger; @@ -23,6 +23,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.PathFinder;
import de.srsoftware.web4rail.Plan;
@ -216,7 +217,7 @@ public class Train extends BaseClass implements Comparable<Train> { @@ -216,7 +217,7 @@ public class Train extends BaseClass implements Comparable<Train> {
public String automatic() {
if (isNull(autopilot)) {
autopilot = new Autopilot();
autopilot.start();
Application.threadPool.execute(autopilot);
if (isSet(currentBlock)) plan.place(currentBlock);
}
return t("{} now in auto-mode",this);
@ -740,6 +741,9 @@ public class Train extends BaseClass implements Comparable<Train> { @@ -740,6 +741,9 @@ public class Train extends BaseClass implements Comparable<Train> {
tile.setTrain(this);
} else {
tile.setTrain(null);
if (Route.freeBehindTrace) try {
tile.unset(route);
} catch (IllegalArgumentException e) {}
trace.remove(i);
i--; // do not move to next index: remove shifted the next index towards us
}
@ -803,7 +807,7 @@ public class Train extends BaseClass implements Comparable<Train> { @@ -803,7 +807,7 @@ public class Train extends BaseClass implements Comparable<Train> {
try {
Thread.sleep(1000);
plan.stream(t("Simulating movement of {}...",this));
new Thread() {
Application.threadPool.execute(new Thread() {
public void run() {
for (Tile tile : route.path()) {
if (isNull(route)) break;
@ -820,7 +824,7 @@ public class Train extends BaseClass implements Comparable<Train> { @@ -820,7 +824,7 @@ public class Train extends BaseClass implements Comparable<Train> {
}
}
};
}.start();
});
} catch (InterruptedException e) {
e.printStackTrace();
}

5
src/main/java/de/srsoftware/web4rail/tiles/Bridge.java

@ -7,6 +7,7 @@ import java.util.Map; @@ -7,6 +7,7 @@ import java.util.Map;
import org.json.JSONObject;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.Connector;
import de.srsoftware.web4rail.Route;
@ -51,7 +52,7 @@ public abstract class Bridge extends Tile { @@ -51,7 +52,7 @@ public abstract class Bridge extends Tile {
@Override
public Tile load(JSONObject json) {
if (json.has(COUNTERPART)) {
new Thread() {
Application.threadPool.execute(new Thread() {
@Override
public void run() {
try {
@ -61,7 +62,7 @@ public abstract class Bridge extends Tile { @@ -61,7 +62,7 @@ public abstract class Bridge extends Tile {
}
counterpart = (Bridge) plan.get(Id.from(json, COUNTERPART), false);
}
}.start();
});
}
return super.load(json);
}

7
src/main/java/de/srsoftware/web4rail/tiles/Contact.java

@ -11,6 +11,7 @@ import org.json.JSONArray; @@ -11,6 +11,7 @@ import org.json.JSONArray;
import org.json.JSONObject;
import de.srsoftware.tools.Tag;
import de.srsoftware.web4rail.Application;
import de.srsoftware.web4rail.BaseClass;
import de.srsoftware.web4rail.Route;
import de.srsoftware.web4rail.Window;
@ -43,7 +44,7 @@ public class Contact extends Tile{ @@ -43,7 +44,7 @@ public class Contact extends Tile{
boolean aborted = false;
public OffTimer() {
start();
Application.threadPool.execute(this);
}
@Override
@ -232,14 +233,14 @@ public class Contact extends Tile{ @@ -232,14 +233,14 @@ public class Contact extends Tile{
public boolean trigger(int duration) {
activate(true);
new Thread() {
Application.threadPool.execute(new Thread() {
public void run() {
try {
sleep(duration);
activate(false);
} catch (Exception e) {}
}
}.start();
});
return true;
}
@Override

Loading…
Cancel
Save