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(){
}
}
Related
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
I am working on a Java UDP application. There is a thread in the application whose only job is to listen to a server on a specific port.
I wrote the application under the mistaken assumption that the server I am listening to will always be up; this, however, was a bad assumption.
If my application starts after the server is running, then everything works fine. If my application starts before the server is up, or if the server is restarted while my application is running, my application breaks.
MainClass.java
public class MainClass {
public static void main(String[] args){
ListeningClass myListeningClass = new ListeningClass();
Thread listenerThread = new Thread(myListeningClass);
listenerThread.setName("My Listening Thread");
listenerThread.start();
}
}
ListeningClass.java
public class ListeningClass implements Runnable {
private volatile boolean run = true;
private byte[] receiveBuffer;
private int receiveBufferSize;
private DatagramSocket myDatagramSocket;
private DatagramPacket myDatagramPacket;
#Override
public void run(){
try {
myDatagramSocket = new DatagramSocket(null);
InetSocketAddress myInetSocketAddress = new InetSocketAddress(15347);
myDatagramSocket.bind(myInetSocketAddress);
receiveBuffer = new byte[2047];
myDatagramPacket = new DatagramPacket(receiveBuffer, 2047);
while(run){
myDatagramSocket.receive(myDatagramPacket);
byte[] data = myDatagramPacket.getData();
receiveBufferSize = myDatagramPacket.getLength();
// process the data received here
}
} catch (SocketException se){
// do stuff
} catch (IOException ioe){
// do stuff
}
}
public boolean isRun(){
return run;
}
public void setRun(boolean run){
this.run = run;
}
}
Like I said, if my application starts after the server is running, everything works perfectly, just as expected. However, if my application starts before the server is running, then nothing works. Obviously, is is because the thread tries to open the connection once, and if it fails, then it never tries again.
I moved the DatagramSocket open code to within the while block but that wasn't pretty. I got a bunch of "port already bound" errors.
So, how can I reconstruct this so that it works properly?
It's not really a concurrency question. You just need to check the exceptions thrown on receive and handle appropriately. In this case, rebind the socket. See the docs for receive.
For example:
...
while(run) {
try {
myDatagramSocket.receive(myDatagramPacket);
byte[] data = myDatagramPacket.getData();
receiveBufferSize = myDatagramPacket.getLength();
// process the data received here
} catch (IOException ioe) {
// Perhaps use PortUnreachableException but not guaranteed
rebind(myDatagramSocket, myInetSocketAddress);
}
}
private void rebind(DatagramSocket s, InetSocketAddress addr) {
s.bind(addr);
}
I think that should be enough. the point is, you only want to rebind if your receive indicates there's an I/O problem with the server. You're binding for each receive if you place the bind in the loop - which is ok in your happy-path situation.
The important things to note here are the precise points in which the program fails and the type of exception that you're given.
Presumably it fails on line myDatagramSocket.receive(myDatagramPacket);, but double check with the stacktrace on your exception. The second thing to check is the type of exception. Is it a SocketException or a subclass of SocketException? Is there a specific error code? Try to be as specific as possible.
At this point, you should surround the section of code that fails in its own try catch within the while loop. You want to be able to say that should it fail, your thread will sleep and try again after a hiatus (to not bombard the server with requests). And to simply things further, I would section the code in its own method, so you would expect something like:
public class ListeningClass implements Runnable {
private static final int MAX_RETRIES = 30;
private static final int RETRY_SLEEPTIME = 30000;
private volatile boolean run = true;
private InetSocketAddress myInetSocketAddress;
#Override
public void run(){
try {
DatagramSocket myDatagramSocket = new DatagramSocket(null);
myInetSocketAddress = new InetSocketAddress(15347);
myDatagramSocket.bind(myInetSocketAddress);
byte[] receiveBuffer = new byte[2047];
DatagramPacket myDatagramPacket = new DatagramPacket(receiveBuffer, 2047);
awaitRequests(myDatagramSocket, myDatagramPacket)
} catch (SocketException se){
// do stuff
} catch (IOException ioe){
// do stuff
}
}
private void awaitRequests(DatagramSocket myDatagramSocket, DatagramPacket myDatagramPacket) throws SocketException, IOException {
int maxRetries = MAX_RETRIES;
while(run){
try {
myDatagramSocket.receive(myDatagramPacket);
byte[] data = myDatagramPacket.getData();
// Packet received correctly, reset retry attempts
maxRetries = MAX_RETRIES;
process(myDatagramPacket);
} catch (SocketException e) {
maxRetries--;
// Good place to write to log of some kind
if(maxRetries == 0) {
throw e;
}
Thread.currentThread().sleep(RETRY_SLEEPTIME);
// Lets attempt to restablish the connection
reconnect(myDatagramSocket);
}
}
}
private void process(DatagramPacket myDatagramPacket) {
int receiveBufferSize = myDatagramPacket.getLength();
// process the data received here
}
private void reconnect(DatagramSocket myDatagramSocket) {
myDatagramSocket.bind(myInetSocketAddress);
}
public boolean isRun(){
return run;
}
public void setRun(boolean run){
this.run = run;
}
}
Note a couple things. I only caught SocketException because I am assuming the type of exception that you're getting is a SocketException. If you're getting an IOException of some kind, then you should check that. Better still if you're specifying the subtype of that exception. The reason is this: you don't want to blanket handle all errors, but only those pertaining to the server being down. If the program lacks authentication to open the socket, you would want to fail immediately, not continually retry.
The second thing is that I've separated the processing of the packet in its own method, because I think that's the proper thing to do in these cases.
I want to access the instance created in t1 from outside the thread, is this possible? So I can close the socket after the thread is executed.
Network class:
public class Network {
Socket socket;
public void changeConnection(String command)
throws Exception { // Whatever exceptions might be thrown
if (command.equals("connect")) {
socket = new Socket(server, port);
}
else if (command.equals("disconnect")) {
socket.close();
}
}
}
Main class:
public class Project1 {
public static void main(String[] args) throws Exception {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
try {
Network network = new Network();
network.connect("connect");
}
catch (Exception ex) {
}
}
});
t1.start();
Thread.sleep(20000);
network.connect("disconnect");
}
}
Yes, that's possible.
In your code, the t1 variable is local to main(String[] args):
public static void main(String[] args) {
Thread t1 = ...
}
You cannot access local variables from outside the method where they are declared. In order to do so, you just need to turn the local variable into a class member (also known as field or class property). Then you can set the access modifier to define which classes can access it.
public class Project1 {
protected static Thread t1;
public static void main(String[] args) {
t1 = new Thread...
}
}
The t1 inside main() refers to the class member t1. Of course, because your main() method is static, you also need the class member you want to access from within main() to be static. You can set the access modifier of t1.
Another way to do it
But if you want to close the connection after the thread is executed, then why don't you just close it as the last statement of the thread?
public static void main(String[] args) throws Exception {
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
try {
Network network = new Network();
network.changeConnection("connect");
// Do loads of work...
// All work has been done and we're done with the
// connection. Why don't we close it just now?
network.changeConnection("disconnect");
}
catch (Exception exc) {
// Catch the exception properly
}
}
});
t1.start();
}
Or using a lambda expression:
Thread t1 = new Thread(() -> {
// body of run()
});
t1.start();
PS: You should always start class names (like Project1) with an uppercase character.
Why you want to open the socket connection in new thread as a non-static object? Because if you are opening the connection then certainly you want to close the connection.
Now if you are opening it in a new thread and as non-static socket connection object then you have keep your main thread alive who is holding the object/handler of the your socket connection so that in the end you can close it, otherwise socket connection will never be closed and the resources and RAM area it had occupied will never be freed.
Disclaimer: Without understanding your complete requirement it is hard to give you a fitting solution but my speculative solutions for you are as below, choose which fits your case/requirement:
One approach:
Generally, database connections are opened as a static object so that it can be accessed by many threads and later be closed be some/last thread. So, you can create a your SocketConnection class and create a static java.net.Socket object, which will be used by all your threads, and once everything is done over that socket connection then your last thread will close the socket connection.
Another approach (use java.lang.ThreadLocal):
If you want to pass some information/object to other pieces of code without passing it in method parameters then ThreadLocal is your friend. It will help you pass the object to any portion of code which is being executed by same thread. ThreadLocal has thread scope, so now you can understand that anything you will put in ThreadLocal will be valid until that thread is alive.
Read this nice tutorial on how to use ThreadLocal.
Another approach (solely based on the code example you used):
I guess you are using Thread.sleep(20000); so that by this sleep is over your thread t1 would have finished opening socket connection, and then you can do something, and at-last close socket connection.
If that is the case, then using sleep() method like this is not recommended. So, after thread has started, you can check if it has finished execution, and if yes then you can do whatever you wish. Below is code example:
final Network network = new Network();
Thread t1 = new Thread(new Runnable() {
#Override
public void run() {
System.out.println("Thread started...");
try {
network.changeConnection("connect");
}
catch (Exception ex) {
}
}
});
t1.start();
System.out.println("Thread start command executed...");
//Thread.sleep(20000);
while(t1.isAlive()){
//Do nothing...
}
network.changeConnection("disconnect");
As I think your problem, the solution should be like this.
Main class:
public class project1 {
static Thread t1 = null;
public static void main(String[] args) throws Exception {
t1 = new Thread(new Runnable() {
public void run() {
try {
network network = new network();
network.connect("connect");
}
catch (Exception ex) {
}
}
});
t1.start();
Thread.sleep(20000);
network.connect("disconnect");
}
}
Now you can access it anywhere in Project1 class.
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
I created a UDP server. Here's a skeleton
public class UDPserver {
public static void main(String[] args) throws Exception{
while(true){
.... some code ...
packet = new DatagramPacket ( data , data.length, packet.getAddress(), packet.getPort() );
.... some code ...
socket.receive( ... );
}
}
}
Now, i want to make it handle multiple requests, so i checked out that i have to implement Runnable.
public class UDPserver implements Runnable { }
I read that I also need to have a run(). But i don't understand run(). should i put the whole while(true) statement inside run()? what about main()? Can anyone show how to change my code above to handle multiple requests?
thanks
move all the code inside the run method of UDPServer (including the while(true))
In your main method :
UDPServer udpServer = new UDPServer();
udpServer.start();
To make sure that no excpetion won't break your main loop, remember to catch and handle all exceptions that might be rasied inside the while(true) loop
You can also use new thread for each new connection for performing. For example:
class PacketPerforming extends Thread {
DatagramPacket pak;
PacketPerforming(DatagramPacket pak) {
super();
this.pak = pak;
}
public void run() {
// do somethoing with pak
}
}
// in your server thread
while (true) { // i prefered wirte for (;;)
DatagramPacket pak; // take pak object form remote socket
PacketPerforming perform = new PacketPerforming(pak);
perform.start();
}