Java Variables in Threads - java

I've read a few question/answers here but am still a hair confused on how java threading and variables work.
My software opens a continuous URL listener for some events connecting some jacked up version of the REST API, but I'll digress. So here's a summarized block of code.
public static void main(String[] args) {
//open the long-running URL
conn = (HttpURLConnection) url.openConnection();
// Start to receive the event notification.
br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
// Read a complete event. Process the event.
String str = sb.toString();
sb.delete(0, sb.length());
// Parse the alarm and send to the sub-processor if necessary
log4j.debug("Start Event Parsing");
ParseAlarm.parseXML(str);
Thread newAlarm = new Thread(new CreateAlarm());
newAlarm.start();
}
Mind you this is all to fix a bug where if a 2nd event is received before the parsing completes, one of them gets lost.
If I move ParseAlarm.parseXML(str) into the newAlarm thread (which fires additional threads to maintain order) do all of the sub-threads have access to the public variables (some are arrays, some are ints/strings) declared in parseXML or do I need to pass the variables to each sub-thread?
If the public variables declared in parseXML are available to all of the sub-threads of newAlarm, what happens if newAlarm is triggered again by the main script? Do the public parseXML variables clash with the ones in the other thread?
ParseAlarm is as such. Sparing the irreverent portions of code. Mind you it's not setup for threading yet.
public class ParseAlarm {
public static int intAlarmID;
public static String strAlarmDesc;
public static Map<String, String> mXML = new HashMap<String, String>();
public static void ParseXML(String strXML) throws Exception {
for (int i = 0; i < arElementList.length; i++) {
//parse the elements in the XML
}
// Create the alarm ID as an integer for the alarm acknowledgement and the alarm description for the filter
intAlarmID = Integer.parseInt(mXML.get("id"));
strAlarmDesc = mXML.get("alarmDesc");
}
}
I have been able to access the variables declared public from other threads by referencing the them as such:
public static Map mAlarm = ParseAlarm.mXML;
private int intID = ParseAlarm.intAlarmID;
Is this not supposed to happen or am I completely doing this wrong?

Related

Resetting OutputStream so updated variables send

I've come across an issue when sending an object over a local connection. The object will send the first time as expected. However variables of the object are constantly being changed therefore need to be updated when sending to the other connection. This is done through sending messages prompting the other client to listen and wait for the object being sent.
I'm aware that the java.io.ObjectOutputStream.reset() method exists but keep getting the following error:
error: cannot find symbol
output.reset();
Here's how the code is currently structured (Minus lots of non relevant code):
import java.net.*;
import java.util.*
import java.io.*;
public class Client
{
private static Socket cSocket = null;
private static ObjectOutput output = null;
private static Person myPerson = null;
private static String serverHost = "localhost";
public void Run()
{
// Declaring the output
output = new ObjectOutputStream(
cSocket.getOutputStream()
);
}
private static void sendPerson()
{
try
{
output.writeObject( myPerson );
output.reset();
} catch (Exception e)
{
}
}
}
TLDR: Each time sendPerson() is called the other client receives the first object sent to the other client rather than the updated variables. Tried using reset(); but error is thrown.
Would just like the objects updated variables to be sent rather than the initial object always being sent.
To use ObjectOutputStream#reset you have to define your field with such type.
Not ObjectOutput, but ObjectOutputStream.
Like this:
private static ObjectOutputStream output = null;

how to avoid switch statement?

I'm trying to learn client/server in java
until now i got the basics.
here how to accept and serve out many clients
public class Server {
ServerSocket serverSocket;
public void startServer() throws IOException {
serverSocket= new ServerSocket(2000);
while (true){
Socket s= serverSocket.accept();
new ClientRequestUploadFile(s).start(); //here is the first option.
}
}
}
Now suppose i have too many type of options the client can request.
the code will be as follow :
public void startServer() throws IOException {
serverSocket= new ServerSocket(2000);
while (true){
Socket s= serverSocket.accept();
DataInputStream clientStream= new DataInputStream(s.getInputStream());
String requestName=clientStream.readUTF();
switch (requestName){
case "ClientRequestUploadFile": new ClientRequestUploadFileHandler(s).start();break;
case "clientRequestCalculator": new clientRequestCalculatorHandler(s).start();break;
case "clientRequestDownloadFile": new clientRequestDownloadFileHandler(s).start();break;
}
}
}
if there 100 of options,is there any way to avoid switch statement(design-patterns maybe)?
keep in mind that may occur new option in the future.
This seems like an example where something like the Command pattern would be appropriate.
Basically, you want a way to map a given command (in this case, a String), into executing the appropriate behavior.
The simplest way to do this would be to create a Command interface like so:
interface Command {
void execute();
}
Then you can create a Map<String, Command> that holds your commands and maps each incoming String into some helper class that implements Command and does the thing you want to happen when you see that command. Then you would use it something like:
commandMap.get(requestName).execute();
This will, however, require a bit of on-the-fly setup at program startup to build the Map with the command strings and the Command objects. This is a very dynamic way of setting up the mapping, which may be a good or bad thing depending on how often your command set changes.
If your commands are more static, a more elegant way to set this up would be to use an enum to define the various commands and their behaviours. Here's a fairly simple and generic example of how you could do that:
public class CommandPatternExample {
public static void main(String[] args) throws Exception {
CommandEnum.valueOf("A").execute(); // run command "A"
CommandEnum.valueOf("B").execute(); // run command "B"
CommandEnum.valueOf("C").execute(); // IllegalArgumentException
}
interface Command {
void execute();
}
enum CommandEnum implements Command {
A {
#Override
public void execute() {
System.out.println("Running command A");
}
},
B {
#Override
public void execute() {
System.out.println("Running command B");
}
};
}
}
As pointed out in the comments, there's no way to get around having the command to helper object mapping somewhere in your code. The main thing is to not have it in your business logic, which makes the method hard to read, but rather in its own class somewhere.
So what you have is a large-ish switch block that in the end start()s some piece of code. The recommended way is to use existing interfaces, so that would be a Runnable (containing a void method with no parameters, just like your start()).
If you refactor the whole block out into a method, it would have two inputs: the Socket and the the requestName - so its signature would look like this:
Runnable getRequestCommand(Socket s, String request)
which would contain your switch block and returned something like
if ("ClientRequestUploadFile".equals(request)) {
return new ClientRequestUploadFileHandler(s);
}
// etc
Again using preexisting interfaces, this is a BiFunction<Socket, String, Runnable> (it requires the request string and the socket as input and returns the handler runnable).
Now you can split each individual case and create such a function:
BiFunction<Socket, String, Runnable> upload = (s, req) -> {
return "ClientRequestUploadFile".equals(req)
? new ClientRequestUploadFileHandler(s)
: null;
}
If you do the same for the other cases and store these in a Collection<BiFunction<Socket, String, Runnable>> (let's call it handlers), your getRequestCommand() method above looks like
Runnable requestHandler = null;
for (BiFunction<Socket, String, Runnable> handler : handlers) {
requestHandler = handler.apply(s, request);
if (requestHandler != null) { break; } // found the match
}
return requestHandler;
Now your switch actually also starts the created Runnable, so you can also if (requestHandler != null) { requestHandler.run(); } here and not return it back to the caller. As a single line, this is handlers.stream().map(h -> h.apply(s, request)).findFirst(Objects::nonNull).ifPresent(Runnable::run).
Anyway, now you're stuck with creating all the BiFunction<>s in the original class, but you can externalize them, eg. to an enum.
enum RequestHandler {
FILE_UPLOAD("ClientRequestUploadFile", ClientRequestUploadFileHandler::new),
CALCULATE("clientRequestCalculator", ClientRequestCalculatorHandler::new),
// ...
;
// the String that needs to match to execute this handler
private String request;
// creates the runnable if the request string matches
private Function<Socket, Runnable> createRunnable;
private RequestHandler(String r, Function<Socket, Runnable> f) {
request = r; createRunnable = f;
}
// and this is your handler method
static void runOnRequestMatch(Socket socket, String request) {
for (RequestHandler handler : values()) {
Runnable requestHandler = request.equals(handler.request)
? handler.createRunnable.apply(socket)
: null;
if (requestHandler != null) {
requestHandler.run();
break;
}
}
}
}
And in your client code, you'd get
// ...
Socket s= serverSocket.accept();
DataInputStream clientStream= new DataInputStream(s.getInputStream());
String requestName=clientStream.readUTF();
RequestHandler.runOnRequestMatch(s, requestName);
Now you've ended up with far more code than before, but the handling itself is removed from the class accepting the socket, so better single responsibility; this allows you to add functionality by adding a value to the enum without needing to touch your original code.
A simpler version would be to create the functions collection in a method by simply doing
Collection<BiFunction<Socket,String,Runnable>> createMappings() {
return Arrays.asList(
createMapping("ClientRequestUploadFile", ClientRequestUploadFileHandler::new),
createMapping("clientRequestCalculator", ClientRequestCalculatorHandler::new),
);
}
private BiFunction<Socket,String,Runnable> createmapping(String req, Function<Socket, Runnable> create) {
return (s, r) -> req.equals(r) ? create.apply(s) : null;
}

How to shutdown akka from java

I have an akka (akka-actor_2.11) application that we use for stress testing one of our systems. The top level actor called RunCoordinatorActor is able to know based on responses coming from its subordinates when the work is finished.
When the work is finished the RunCoordinatorActor makes a call to getContext().system().shutdown() and then in the main method there is a loop checking for the system.isTerminated() call to return true. All works fine and I am happy with the way it works. However both system.sutdown() and system.isTerminated() methods are marked as deprecated and I am trying to figure out the right way to implement a graceful shutdown without using them.
Here is my main class:
public static void main(String[] args) throws Exception {
if (new ArgumentsValidator().validate(args)) {
// If the arguments are valid then we can load spring application
// context on here.
final ApplicationContext context = new AnnotationConfigApplicationContext(
M6ApplicationContext.class);
// Use an akka system to be able to send messages in parallel
// without doing the low level thread manipulation ourselves.
final ActorSystem system = context.getBean(ActorSystem.class);
final ActorRef runCoordinator = system.actorOf(SPRING_EXT_PROVIDER.get(system)
.props("RunCoordinatorActor"), "runCoordinator");
Thread.sleep(1000);
runCoordinator.tell(new StartTesting(), ActorRef.noSender());
do {
LOGGER.info("Waiting for the process to finish");
Thread.sleep(60000L);
// What would be the alternative for isTerminated() code below
} while (!system.isTerminated());
}
}
and here is my call to shutdown inside the RunCoordinator class:
#Named("RunCoordinatorActor")
#Scope("prototype")
public class RunCoordinator extends UntypedActor {
#Override
public void onReceive(Object message) throws Exception {
....
if (message instanceof WorkDone) {
getContext().system().shutdown();
}
}
}
I can see there is another method called terminate() that returns a Future and if I replace the shutdown call with that it all works OK too.
if (message instanceof WorkDone) {
Future<Terminated> work = getContext().system().terminate();
// But where should I put the call work.isCompleted()
// and how would I make the main aware of it
}
I could find some scala examples on here shutdown-patterns-in-akka-2 but they still use system.shutdown in the end so not sure how up to date that post still is.
Thank you in advance for your inputs.
The solution was not that hard to find once I looked closer into the ActorSystem API.
All I had to do was to add this to my RunCoordinator class:
if (message instanceof WorkDone) {
getContext().system().terminate();
}
And had a Future<Terminated> workDone = system.whenTerminated(); defined in my main class which after the change became:
public static void main(String[] args) throws Exception {
if (new ArgumentsValidator().validate(args)) {
// If the arguments are valid then we can load spring application
// context on here.
final ApplicationContext context = new AnnotationConfigApplicationContext(
M6ApplicationContext.class);
// Use an akka system to be able to send messages in parallel
// without doing the low level thread manipulation ourselves.
final ActorSystem system = context.getBean(ActorSystem.class);
final Future<Terminated> workDone = system.whenTerminated();
final ActorRef runCoordinator = system.actorOf(SPRING_EXT_PROVIDER.get(system)
.props("RunCoordinatorActor"), "runCoordinator");
runCoordinator.tell(new StartTesting(), ActorRef.noSender());
do {
LOGGER.info("Waiting for the process to finish");
Thread.sleep(60000L);
} while (!workDone.isCompleted());
}
}
All worked very well after this. I am still surprised google cold not take me to any existing example showing how to do it.

JACOB event registration

I'm trying to use JACOB to obtain a callback whenever a slide show starts or ends using the following:
public class Test {
public static void main(String[] args) {
ActiveXComponent oApp = new ActiveXComponent("PowerPoint.Application");
Dispatch presentations = oApp.getProperty("Presentations").toDispatch();
Dispatch presentation = Dispatch.call(presentations, "Open", "C:\\Users\\Bob\\Documents\\test.ppt").toDispatch();
new DispatchEvents(oApp, new Handler());
}
}
public class Handler {
public void SlideShowBegin(Variant[] args) {
System.out.println("here");
}
}
However, I'm coming a bit unstuck, the result of the above is:
GetEventIID: couldn't get IProvideClassInfo
Exception in thread "main" com.jacob.com.ComFailException: Can't find event iid
at com.jacob.com.DispatchEvents.init3(Native Method)
at com.jacob.com.DispatchEvents.<init>(DispatchEvents.java:138)
at com.jacob.com.DispatchEvents.<init>(DispatchEvents.java:99)
at com.jacob.com.DispatchEvents.<init>(DispatchEvents.java:72)
at tester.Test.main(Test.java:28)
Does anyone have any ideas? Searching has come up pretty short. I've tried using the 4 argument constructor of DispatchEvents, supplying "Powerpoint.Application" and the full path to the powerpoint exe as the last two arguments, but no difference.

Thread's run does not see its array size increase

I am currently working on a Java homework. I am asked to create a basic DNS server.
There is an UDPSender class which is a thread listening on port 53.
There is also another thread which is called UDPManager.
UDPManager starts a thread with a nested runnable class which holds an ArrayList of DatagramPacket. The UDPSender aggregates the UDPManager and whenever it receives an UDP packet, it sends it to the manager for him to add it to the arrayList.
import java.net.DatagramPacket;
import java.util.ArrayList;
import java.util.HashMap;
public class UDPManager {
private UDPManagerRunnable manager;
public UDPManager(String hostsFile, String remoteDNS, boolean localResolution) {
manager = new UDPManagerRunnable(hostsFile, remoteDNS, localResolution);
new Thread(manager).start();
}
public void managePacket(DatagramPacket p) {
manager.managePacket(p);
}
public void close() {
manager.close();
}
private class UDPManagerRunnable implements Runnable {
private ArrayList<DatagramPacket> packets;
private HashMap<Integer, String> clients;
private boolean localResolution;
private boolean running;
private String hostsFile;
private String remoteDNS;
public UDPManagerRunnable(String hostsFile, String remoteDNS, boolean localResolution) {
packets = new ArrayList<DatagramPacket>();
clients = new HashMap<Integer, String>();
this.localResolution = localResolution;
this.running = true;
this.hostsFile = hostsFile;
this.remoteDNS = remoteDNS;
}
public void managePacket(DatagramPacket p) {
packets.add(p);
System.out.println("Received packet. "+packets.size());
}
public void close() {
running = false;
}
public void run() {
DatagramPacket currentPacket = null;
while(running) {
if(!packets.isEmpty()) {
currentPacket = packets.remove(0);
byte[] data = currentPacket.getData();
int anCountValue = data[Constant.ANCOUNT_BYTE_INDEX];
if(anCountValue == Constant.ANCOUNT_REQUEST)
this.processRequest(currentPacket);
else if(anCountValue == Constant.ANCOUNT_ONE_ANSWER)
this.processResponse(currentPacket);
}
}
}
private void processRequest(DatagramPacket packet) {
System.out.println("it's a request!");
}
private void processResponse(DatagramPacket packet) {
System.out.println("it's a response!");
}
}
}
This is the UDPManager. The packets are transmitted to the manager correctly as the System.out.println correctly displays "Received packet." and the size of the array does increase. The problem I'm running into is that inside the "run()" it never see the size increasing. The weird thing is that it works perfectly fine in debug.
Any idea why it's acting this way?
Thanks a lot for your help.
The problem is, that your first thread is putting the new data into the packets variable, but for the second thread this is not visible. You should synchronize the access to the array.
When you start a second thread all variables are copied. The second thread is only working on the copies. You need to synchronize access to this variables, so changes are made visible to the other threads.
you should synchronize packets when you access or modify it

Categories

Resources