Thread does not stopped using flag as volatile - java

In following code i am trying to start and stop the server on button using java applet.Start works good using thread but i want to stop the server on button. I have used volatile variable.Still i am not getting the server stop..
here is code:
public class TCPServer extends Thread {
public static final int SERVERPORT = 8002;
private boolean running = false;
public volatile boolean stop = false;
public Socket client = null;
public static void main(String[] args) {
ServerBoard frame = new ServerBoard();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.pack();
frame.setVisible(true);
}
public void run() {
super.run();
running = true;
try {
System.out.println("Server Has Started........ \n Waiting for client........");
ServerSocket serverSocket = new ServerSocket(SERVERPORT);
try {
while (!stop && running) {
client = serverSocket.accept();
System.out.println("Connection Accepted......");
BufferedReader in = new BufferedReader(new InputStreamReader(client.getInputStream()));
String usercmnd = in.readLine();
if (usercmnd != null) {
Runtime runtime = Runtime.getRuntime();
Process p = runtime.exec(usercmnd);
}
}
if (stop) {
serverSocket.close();
client.close();
System.out.println("Server Has Stopped");
System.exit(0);
}
} catch (Exception e) {
System.out.println("Error");
e.printStackTrace();
}
} catch (Exception e) {
System.out.println("Error");
e.printStackTrace();
}
}
public void requestStop() {
stop = true;
}
}
But whenever i click the stop button which will stop the server.Its not showing any output on console as i expected by the code.Its also not showing any error
here is code of stop button
stopServer = new JButton("Stop");
stopServer.addActionListener(new ActionListener() {
#Override
public void actionPerformed(ActionEvent e) {
stopServer.setEnabled(false);
startServer.setEnabled(true);
mServer = new TCPServer();
mServer.requestStop();
}
});

It doesn't stop because you create a new instance before stopping it and you don't even start it first while you are supposed to call requestStop() on your current instance of TCPServer.
// Here you create a new instance instead of using the existing one
mServer = new TCPServer();
mServer.requestStop();

in your ActionListener implementation for the stop button, you are accessing a different instance of TCPServer (as you are creating a new one). So you set the value "Stop" to a second object. It has no impact on the first instance that was created with the start button.
Try to instanciate the TCServer outside of your implementation of the action listener for both buttons and use that single instance for both.

Due to https://docs.oracle.com/javase/7/docs/api/java/net/ServerSocket.html#accept()
ServerSocket::accept is a blocking method, so stop variable can only be checked between successful connections.
You can either set a ServerSocket timeout using ServerSocket::setSoTimeout (and catch SocketTimeoutException), or interrupt Server thread and catch InterruptedException.
Both exceptions will be throwed from ServerSocket::accept.
Note, that thread interruption is highly preferred over timeouts and repeatly exception catching.

Try this:
public void requestStop() {
stop = true;
interrupt();
}
However, in this case, we can not guarantee, that already processing logic will successfully shutdown.
Also, you try invoke requestStop for new instance of TCPServer, instead already existing.

your code client = serverSocket.accept(); is blocking. So once you clicked "stopServer" button, you requested the stop, but it will be acted upon only once a client sends a next request to the server. What you need to do is to run your logic in your method run() in a separate thread and catch there InterruptedException and ClosedByInterruptException and clean up and return there. On your stopButton click you will invoke interrupt() method on your Thread. Read about it in here

Related

Starting ServerSocket on Java with User Interface(Swing) Freezes

Good day,
I have an infinite loop for a ServerSocket, working fine... The problem is when I try to start the ServerSocket with a button. My user interface "Freeze" don't move, anything, but the server is up and fine, here I have a ScreenShot:
http://i.gyazo.com/15d331166dd3f651fc7bda4e3670be4d.png
When I press the button "Iniciar" means Start server, the User Interface Freezes (ServerSocket infinite loop). I can't change my code because its working fine.
public static void iniciarServer() {
try {
appendString("\nServidor iniciado.");
System.out.println("asdasd");
} catch (BadLocationException e1) {
e1.printStackTrace();
}
try {
ss = new ServerSocket(1234, 3);
while (true) {
System.out.println("Esperando conexiones...");
appendString("\nEsperando conexiones...");
Socket s = ss.accept();
System.out.println("Conexión entrante: " + s.getRemoteSocketAddress());
appendString("\nConexión entrante: " + s.getRemoteSocketAddress());
conexiones++;
//System.out.println("Debug: conexiones SERVER: " + conexiones);
MultiThread mt = new MultiThread(s, conexiones);
mt.start();
///////////////////////////////////////////////////////////////
}
} catch (IOException e) {
System.out.println("Error Server: " + e.getMessage());
} catch (BadLocationException e) {
e.printStackTrace();
}
stopServer();
}
appendString();
Is for add some text to the JTextPane, but doesnot work because the UI freezes.
Is there any way to do an user interface that don't freeze by the infinite loop?
Thanks!
Swing is a single threaded framework, meaning any blocking or long running operation executed within the context of the Event Dispatching Thread will prevent it from processing the Event Queue, making your application hang.
It's also not thread safe, so you should never try and modify the state of any UI component from out side of the EDT.
Take a look at Concurrency in Swing and Worker Threads and SwingWorker for more details
public class ServerSocketWorker extends SwingWorker<Void, String> {
private JTextArea ta;
public ServerSocketWorker(JTextArea ta) {
this.ta = ta;
}
#Override
protected void process(List<String> chunks) {
for (String text : chunks) {
ta.append(text);
}
}
#Override
protected Void doInBackground() throws Exception {
ss = new ServerSocket(1234, 3);
while (true) {
publish("\nEsperando conexiones...");
Socket s = ss.accept();
publish("\nConexión entrante: " + s.getRemoteSocketAddress());
conexiones++;
//System.out.println("Debug: conexiones SERVER: " + conexiones);
MultiThread mt = new MultiThread(s, conexiones);
mt.start();
///////////////////////////////////////////////////////////////
}
}
#Override
protected void done() {
stopServer(); //??
}
}
To start it, you could use something like...
public void iniciarServer() {
ServerSocketWorker worker = new ServerSocketWorker(textAreaToAppendTo);
worker.execute();
}
As an example
The method ServerSocket.accept() is a blocking method. This means that Socket s = ss.accept(); stops the current thread until a connection to the server socket is opened.
Event dispatching in Swing is single threaded, the while loop and the blocking operation mentioned above, will keep the thread 'busy' and block all other interactions with the UI.
You should run your entire while loop in a separate thread. When you want to stop the server, you should also ensure that the while loop is exited and the thread completes execution.

My GUI freezes after I recreate a ServerSocket

My Server is build around support to update the listening socket, by doing so I use the following method. my problem occurs after this method is called for the second time, this is first called at start up from the main method then later it is called by clicking a button in a JFrame. what happens is that the JFrame freezes when this method is called via button, as you can see by the code I tried to make this method run a server in a new thread but it hasn't changed my outcome. Does anyone know how to fix this? or at least what is causing it? also any code after the method is called in the main doesn't get execute, so I believe it is a thread problem. (MiniServer extends Thread and is used to handle each connected client individually)
public static void startListening(final int port)
{
listeningThread = new Thread()
{
public void run()
{
try {
serverSocket = new ServerSocket(port);
while(!stop)
{
boolean loop = true;
while (loop)
{
serverSocket.setSoTimeout(1000);
try{
clientSocket = serverSocket.accept();
loop = false;
} catch (SocketTimeoutException e){
}
}
if(!clientSocket.equals(null))
{
MiniServer mini = new MiniServer(clientSocket);
mini.start();
clientSocket = null;
}
}
} catch (IOException e) {
}
}
};
listeningThread.run();
}
You need to be calling listeningThread.start(), which will create a new thread. Right now, you're just calling the thread's run() method on the current thread. The first time you do that it works, since you're on the main thread. The second time, though, you're on the UI thread, reacting to the button press. This causes your UI thread to block.

How to run multiple threads concurrently for Automated Selenium testing?

I have one web application from which I can start respective testing process which is in another Java app. I am using Socket Programming for communication between Web app and Java app.
When I request for specific process from web app then SocketServer from Java app hears request and start one thread for Testing process.
Testing process will initialize FirefoxDriver and start browser and do further test process.
My problem is, when I request for another process with different process name then It again creates second thread and start firefox browser but this time it is not considering my second process, it started to do same process which is first thread have.
I do not understand what to do...For every process I created a new thread but further it will doing same process.
My inputs are correctly received at Java app.
Please help me How can I do the concurrent thread safe processing?
I am using GWT,Java, Seleniun FirefoxDriver.
here is the Server code which is running in background and listen client request:
static final int PORT = 6789;
public static void main(String args[]) {
ServerSocket serverSocket = null;
Socket socket = null;
try {
InitializeApplication application = new InitializeApplication();
application.initialize();
serverSocket = new ServerSocket(PORT);
} catch (Exception e) {
log("Exception in SocketServerExecutor !!!",e);
}
while (true) {
try {
socket = serverSocket.accept();
} catch (Exception e) {
log("Exception in SocketServerExecutor !!!",e);
}
Thread thread = new Thread(new SocketServerThread(socket));
thread.start();
}
}
and this is the Thread which start process:
private Socket client;
public SocketServerThread(Socket serverSocket) {
this.client = serverSocket;
}
/**
* Starts appropriate process depending on process name from input.
* Input string contains:
* process name
*/
public void run() {
DataOutputStream outputStream = null;
String param = null;
try{
log("Just connected to "+ client.getRemoteSocketAddress());
try {
while ((param = in.readUTF()) != null){
log("got parameteres from client (i.e. from web app): "+param);
break;
}
} catch (Exception e) { }
if(param!=null && !param.isEmpty()){
String process = params[0];
ProcessManager manager = new ProcessManager();
if(process.equals("testUser"))
manager.startUserProcess(process);
else if(process.equals("testCustomer"))
manager.startCustomerProcess(process);
}
}catch(Exception exc){
if(exc instanceof SocketTimeoutException)
log("Socket timed out! [SocketServerThread]",exc);
else if(exc instanceof BindException)
log("BindException in SocketServerThread !!!",exc);
log(Level.SEVERE, "Exception in SocketServerThread !!!",exc);
}
}
and this is ProcessManager:
public void starUserProcess(String siteName) {
ExecutorService executerService = null;
try{
Callable<Object> callable = new ProcessThread(siteName);
executerService = Executors.newCachedThreadPool();
Future<Object> future = executerService.submit(callable);
future.get();
log("[ProcessManager] Process completed for "+process);
System.exit(0);
}catch (Exception e) {
log("[ProcessManager]::Exception");
log(ex);
}
}
ProcessThread will initialize all required things and Firefox browser and start process.
Client is new every time which contains input.
One of two things that I can thing of off the top of my head could be happening.
You are passing a paramater into your run() function that links back to the initial thread or...
You are using a shared variable that is accessible to all threads and the variable is either not being updated properly, or not being updated at all.
If you could include an SSCCE, that would help us determine where the problem truly lies.
Got the solution: I created the ExecutorService using newSingleThreadExecutor() instead of newCachedThreadPool() and also setDeamon(True) for every newly created ServerThread.
Here is the Executor documentation

calling new thread inside is constructor

Is it correct to create a thread and call its start() method inside a class' constructor as done here?
public class Server implements Runnable {
private ServerSocket server;
public Server(int port) {
try {
//Opens a new server
server = new ServerSocket(port);
} catch (IOException ioe) {
ioe.printStackTrace();
}
new Thread(this, "Server").start();
}
#Override
public void run() {
}
}
IMHO, do not do this. You're allowing the this reference to escape during construction.
Granted, your code isnt doing it but what if your code looked like this:
public Server(int port)
{
new Thread(this, "Server").start();
try
{
//Opens a new server
server = new ServerSocket(port);
}
catch (IOException ioe){ ioe.printStackTrace(); }
}
#Override
public void run(){
if(server == null)throw new NullPointerException();// this may happen
}
}
The server reference may be null even though no exception occurs. This is because the Thread will use the created runnable and invoke the run method even if the constructor of your class hasn't finished.
Server s = new Server();
Thread t = new Thread(s, "Server").start();
is more testable. It allows you to create an instance of Server and unit test its methods without spawning a thread.
A couple more good reasons to split the Thread.start() from the constructor:
If you ever want to use some other framework/system to run the threads, such as a java.util.concurrent.Executor, you may do so.
If you ever want to interrupt the thread, you need a reference to it. Creating the Thread in a separate line of code makes this somewhat more routine / idiomatic. e.g.
Thread rememberMe = new Thread(server).start();
In your original code, Server could have a field to remember myThread, but it didn't.
public class Server implements Runnable
{
private ServerSocket server;
/**
* Because the constructor is private, the only way to instantiate a Server is through
* the static factory method.
* If there are any instantiation problems, the static factory method will fail in
* first line, before it is put into a thread.
* It will be put into a thread before being released.
**/
public static Server startServer ( int port )
{
Server server = new Server ( port ) ;
new Thread ( server , "Server" ) . start ( ) ;
return server ;
}
private Server(int port)
{
try
{
//Opens a new server
server = new ServerSocket(port);
}
catch (IOException ioe){ ioe.printStackTrace(); }
// don't release me into the wild yet!
// new Thread(this, "Server").start();
}
#Override
public void run(){
}
}

How to specify notification between threads if they don't have common data in Java

I have a thread in Java which starts a HttpService.
ProcessBuilder pb = new ProceeBuilder(command);
Process process = pb.start();
process.waitFor();
I have another thread which checks if the service is started.
while (result != 0) {
ServerSocket socket = new ServerSocker(port);
socket.close();
result = 0
catch (BindException be) {
result = 1;
}
}
Now I need to somehow get information about whether the service has failed to start or it's successfully started. I need to get this back to the Main class which started both of these threads in order to proceed. Something like
while (!started || !failed) {
wait for getting information from the threads.
}
What can you advise?
Thank you.
How about using a callback that you pass to both threads?
(omitted try-catches)
public class MyCallback {
private Boolean processSuccess;
private Boolean serviceSuccess;
public synchronized void notifyProcessStart(boolean success) {
this.processSuccess = success;
this.notifyAll();
}
public synchronized void notifyServiceCheck(boolean success) {
this.serviceSuccess = success;
this.notifyAll();
}
public synchronized void waitForResult() {
while(processSuccess == null || serviceSuccess == null) {
this.wait();
}
// ... do something good
}
}
I am very sorry but I am afraid that your code that checks that service is started has bug.
This code is running very quickly, starts server socket and immediately closes it. If you mean that this thread should exit when process is started listening to the same port it is wrong. Your process has 50% of chance to start successfully and other 50% to fail because when it is trying to start listening to the port your watch dog is listening to the same port itself.
So, I believe that you should try to run process using ProcessBulder (exactly as you are doing) and then start delayed watchdog task that tries to connect to this port, i.e.
private boolean isServiceRunning() {
int port = 123;
try {
new Socket("localhost", port).close();
return true;
} catch (IOException e) {
return false;
}
}
This method should be called from separate thread. The best way to implement thread is to use some tool that does it for you. In this case java.util.Timer is the best choice. I am suggesting to run periodic task that will call our method isServiceRunning() and cancel itself if result is true:
new Timer().schedule(new TimerTask() {
#Override
public void run() {
if(isServiceRunning()) {
this.cancel();
}
}
}, new Date(), 10000);
But if this solution is not good for you I'd suggest you to implement interthread communication using wait() and notfify(). Do not forget that both must be in synchronized block.
Good luck!
You can try using boolean flags. Adapting your example code:
Thread 1:
ProcessBuilder pb = new ProcessBuilder(command);
Process process = pb.start();
process.waitFor();
if(!wasConnectionEstablished()) {
setConnectionFailed(true);
}
Thread 2:
while ((result != 0) && (!isConnectionFailed())) {
ServerSocket socket = new ServerSocker(port);
socket.close();
result = 0
catch (BindException be) {
result = 1;
wait(timeout);
}
}
if(isConnectionFailed())
throw new ConnectionFailedException();
else setConnectionEstablished(true);
//continue normal execution

Categories

Resources