So I have a pretty complex (for me) project for my uni. I have to essentially create a Spotify-like program using the Event Delivery System with sockets and threads. To put my problem simply, I want to run 3 broker instances at the same time. Broker.java class extends the Node.java class in which there is an ArrayList:
public static ArrayList<Broker> BrokerList= new ArrayList<Broker>();
in which I want to add each broker node as I open it. Until I solve my problem my Broker Main class looks like this and I want to run 3 instances of this main where I manually change the port each time before I run it:
public class BrokMain {
public static void main(String[] args) throws InterruptedException {
Broker brok = new Broker(4446, "localhost");
brok.startServer();
}
}
and the startServer method inside Broker class looks like this:
public void startServer() {
ServerSocket listenerSocket = null;
BrokerList.add(this);
this.brokHash = hashString(ipAddress + Integer.toString(this.port));
try {
listenerSocket = new ServerSocket(port);
while (true) {
System.out.println("Server is up and waiting ");
listenerSocket.accept();
Thread t = new Thread(this);
t.start();
t.join();
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
So clearly in this method I add this broker to the BrokerList, but even if I run 3 different instances of the brokMain, whenever I try to print the size of the list, I get 1. I feel like this is a thread sychronization issue? Any suggestions?
Related
#Test
public void testMain1() throws Exception {
Runnable t1 = new Runnable() {
public void run() {
String[] str1 = {"noproxyconfig/serverA.dat"};
try {
SIMLConcentratorMain.main(str1);
} catch (Exception e) {
e.printStackTrace();
}
}
};
Runnable t2 = new Runnable() {
public void run() {
String[] str2 = {"noproxyconfig/serverB.dat"};
try {
SIMLConcentratorMain.main(str2);
} catch (Exception e) {
e.printStackTrace();
}
}
};
new Thread(t1).start();
new Thread(t2).start();
TimeUnit.SECONDS.sleep(5);
}
Basically I am trying to start main method two times with different arguments (which is starting two servers) . Right now I am achieving this using multithreading but I think its running in same JVM. But I want to start both servers in different JVM. I created Juint test and created two thread and calling both threads.
With Remote Method Invocation (RMI) you can run on two different machine(so two JVM)
you can use virtual machine
1-Create Rmi Methode
2-Start servers in many machines
3-Start your test
I was tasked to write a small server application. It is supposed to be started via the console and then run in the background, processing some network traffic and calculating stuff locally until it receives a shutdown signal. I am pretty sure i can handle all of that - except the very basic application architecture. I am super unsure how to bring my main loop to wait for the application to finish. So here is my current code, cleaned up and omitting unnecessary parts.
public class TestServer {
public static Logger logger;
private static Boolean abortStartup = false;
private static ServerModule server;
public static void main(String[] args) {
System.out.println("Starting Server...");
initializeServer(); //this function reads config file, and initializes all variables and stuff. If anything goes wrong, abortStartup is set to true
if (!abortStartup) {
runMainLoop();
}
if (!abortStartup) {
cleanup(); //clean up all initialized variables and objects
}
System.out.println("Goodbye.");
}
private static void runMainLoop() {
//This is the main loop. Run this until application terminates.
logger.log(null, "Starting main loop...", Logger.LOGLEVEL_NOTE);
server.run();
while (server.isAlive()) {
//wait until server dies.
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
logger.log(null, "Interrupted during wait for main thread.", Logger.LOGLEVEL_ERROR);
}
}
logger.log(null, "Done.", Logger.LOGLEVEL_NOTE);
}
ServerModule looks like this:
public class ServerModule{
public Boolean shutdown = false;
private Boolean stayAlive = true;
public ServerModule(){
//setup everything
}
public void run() {
//initalize timers, instantiate objects etc.. add listeners and everything. At some point, a network message will set stayAlive to false;
}
public Boolean isAlive() {
return stayAlive;
}
Now for the actual question: is there a more elegant or more efficient way to go about this? i am talking about this part specifically:
while (server.isAlive()) {
//wait until server dies.
try {
Thread.sleep(10000);
} catch (InterruptedException e) {
logger.log(null, "Interrupted during wait for main thread.", Logger.LOGLEVEL_ERROR);
}
Is thread.sleep okay here? Could or should i even omit it? I want to wait here at this very point of my code, so i can clean up after execution stops.
You can make your server something runnable, pack that into a Thread and join!
Example
public static void main(String[] args) throws InterruptedException {
Thread t = new Thread(() -> {
try {
Thread.sleep(5000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
System.out.println("Starting Server!");
t.start();
t.join();
System.out.println("Server is done!");
}
Also you can use CountDownLatch for your purpose, see example:
public class ServerModule extends Thread {
private final CountDownLatch latch;
ServerModule(CountDownLatch latch) {
this.latch = latch;
}
#Override
public void run() {
try {
Thread.sleep(1000L);
//decrease counter of the latch when job is done
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// as ctor arg use threads count for countdown
CountDownLatch latch = new CountDownLatch(1);
System.out.println("Start server");
ServerModule serverModule = new ServerModule(latch);
serverModule.start();
try {
//waiting until latch count will be 0
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Server is done");
}
}
Also with CountDownLatch you can create multiple server instances and waiting them in main thread until they are all done.
It depends on how you're managing your threads.
At the lowest level Java thread API, your main thread can wait for the server thread to complete with:
serverThread.join();
Look at the Thread API for more options, such as putting a timeout on the join() (so you can take increasingly drastic measures to make it end).
Higher level threading abstractions such as Executor, Future, ForkJoinTask etc. give you the same ability with different APIs. A thorough exploration of these is beyond the scope of a SO answer -- Oracle has tutorials on concurrency, or there are books.
Folks. I'm newbie in network programming and come across the following issue. I need to write the server which can maintain a connection with more than one client simultaneously. What I've written is the following:
Main class:
public class Main {
public static void main(String args[]) throws Exception{
ConnectionUtils.waitForClients();
}
}
ConnectionUtils class:
public class ConnectionUtils {
private static ServerSocket server;
static{
try {
server = new ServerSocket(54321);
} catch (Exception e) {
}
}
private static Runnable acceptor = new Runnable() {
#Override
public void run() {
try {
Client c = new Client(server.accept());
new Thread(acceptor).start();
c.sendLine("Hello client \n");
} catch (Exception e) {
}
}
};
public static void waitForClients(){
Thread clientAcceptor = new Thread(acceptor);
clientAcceptor.start();
}
}
and it works, more-or-less. But what is the downside of that approach? I suspect there're too much disadvantage, but I can't catch their.
The problem is that you creating an infinite number of threads where threads are expensive resources. You should be using a ThreadPool to limit the number of threads created in your program.
Consider using Executors instead of using this low-level code, In Oracle documentation about Executors, there is an example similar to what you doing. Check it out!
Heh interesting. I wouldn't expect it to be wrong but it sure isn't how I'd write it.
I'd probably have 1 thread in an infinite (semi-infinite with stop condition) loop that accepts and spawn threads, rather than something that looks like a recursive method but isn't. However as far as I can see it's not wrong.
Having said that, if you don't use your main thread for anything, why not do something like (and keep in mind i'm not a network programmer either)
public class ConnectionUtils {
protected boolean stop = false;
public static void waitForClients() {
while (!stop) {
Client c = new Client(server.accept());
new Thread(new ClientDelegate(c)).start();
}
}
}
public static class ClientDelegate implements Runnable {
private Client client;
public ClientDelegate(Client c) { this.client = c; }
public static void run() {
c.sendLine("Hello client\n");
}
}
I have a class which encapsulates a Server Socket i.e. a server functionality.
The interface of the class is:
class Server{
public void start();
public void stop();
}
the start is as follows:
public void start(){
ExecutorService tp = Executors.newSingleThreadExecutor();
while(!stop){
try {
Socket clientConnection = serverSocket.accept();
tp.execute(new ClientProcessor(clientConnection));
} catch (IOException e) {
stop = true;
}
}
I have trouble figuring out how I would start this without blocing my main.
I mean I need to start the server from a background thread so I thought of the following:
ExecutorService tp2 = Executors.newSingleThreadExecutor();
tp.submit(new Runnable(){
public void run(){
Server s = new Server();
s.start();
}
});
}
But what I want is to know that the server started and did not throw an exception. How can I do that?
I.e. how can I know from my main thread that the background server started fine and so I can continue with the rest actions?
Start the server.
Wait a bit.
Try to connect to it on the local stack. If the connect succeeds, you have a winner - just close the temp connection.
Here is a very simple example (though there are many better - and more complicated - ways):
interface Server implements Thread{
public void startup();
public void shutdown();
}
class MyServer implements Server{
private Exception serverError=null;
ExecutorService singleThreadManager;
public Exception getServerError(){
return serverError;
}
public void run(){
while(!stop){
try {
Socket clientConnection = serverSocket.accept();
singleThreadManager.execute(new ClientProcessor(clientConnection));
} catch (IOException e) {
serverError = e;
// stop = true;
shutdown(); // shutdown cleanly after exception
}
}
}
public void startup(){
singleThreadManager = Executors.newSingleThreadExecutor();
// do setup tasks and then
start(); // thread.run() will now be called asynchronously
}
}
public static void main (String ... args){
MyServer s = new MyServer();
s.startup();
// whenever you want you can now call
Exception x = s.getServerError();
// to see whether the server has shutdown because of an error.
}
maybe you can implement an Event Handler into your main application. Your main application should be registered as eventlistener to your server class.
Please have a look at the following link, it shows you an example of event handling for C# and the same example for Java
http://scatteredcode.wordpress.com/2011/11/24/from-c-to-java-events/
A simple way of doing this would be to collect all exceptions in a collection and return them to the foreground thread at some point in time.
class Server{
private Collection<? extends Exception> exceptions = new ArrayList<Exception>();
public void start()
{
try{ /* do something*/ }
catch(Exception e)
{
exceptions.add(e)
}
}
public void stop();
public Collection<Exception> getAllExceptions()
{
return exceptions;
}
public boolean checkOk()
{
return 0 == exceptions.size();
}
}
Elaboration on how to transfer data between threads:
If you declared your server similarly to my suggestion above, then we can change the code you have used to spawn your server to transfer the serverStartupOk information:
ExecutorService tp2 = Executors.newSingleThreadExecutor();
final boolean[] result = new boolean[1]; //Final object so it can pass between threads
tp.submit(new Runnable(){
public void run(){
Server s = new Server();
s.start();
result[0] = s.checkOk(); // Retrieve the check from the server, store it in
// final array variable
}
});
boolean serverStartupOk = result[0];
System.out.println("Server startup succesful: " + Boolean(serverStartupOk).toString());
}
Use your own ThreadPoolExecutor instead of the pre-baked ones in Executors. Then override the afterExecute hook provided by TPE to do whatever you want with the exceptions.
I'm reading a bit between the lines here, but it looks like you want to know if the initial listen on the socket succeeded or not. If you wanted to wait and see if any client failed, then there would be no need to run it in a different thread.
If that's correct, then you can catch any exceptions emitted by the initial TCP server socket instantiation before you start the thread to handle client connections. Pass the server in to the new thread, instead of creating it in the new thread.
I have the following RMI server code:
public class ServerProgram {
public ServerProgram() {
try {
LocateRegistry.createRegistry(1097);
Calculator c = new CalculatorImpl();
String name = "rmi://host:port/name";
Naming.rebind(name, c);
System.out.println("Service is bound......");
} catch (Exception e) {
}
}
public static void main(String[] args) {
new ServerProgram();
}
}
When the above program running, it keeps running to wait for client requests. But what I do not understand is what make that program keeps running while it is not in something like while(true){}; and how to stop it from listening, except stopping the whole program?
What makes it keep running is a non-daemon listening thread started by RMI. To make it exit, unbind the name and unexport both the Registry and the remote object, with UnicastRemoteObject.unexportObject().
To stop it, you should call
LocateRegistry.getRegistry().unbind("rmi://host:port/name");
But what I do not understand is what make that program keeps running while it is not in something like while(true){}; and how to stop it from listening, except stopping the whole program?
This is done by a edit non-editdaemon thread. See: What is Daemon thread in Java?
You can test the behavior with this little example:
public class DaemonThread extends Thread
{
public void run(){
System.out.println("Entering run method");
try
{
System.out.println(Thread.currentThread());
while (true)
{
try {Thread.sleep(500);}
catch (InterruptedException x) {}
System.out.println("Woke up");
}
}
finally { System.out.println("run finished");}
}
public static void main(String[] args) throws InterruptedException{
System.out.println("Main");
DaemonThread t = new DaemonThread();
t.setDaemon(false); // Set to true for testing
t.start();
Thread.sleep(2000);
System.out.println("Finished");
}
}
The setting prevents the JVM to shut down. after System.out.println("Finished"); you still see the thread running with it's "Woke up" log outputs.