i'm stuck with this code, and i think that i'm missing something really important.
when the thread is running i can add message to the vector
but when it calls notify it seems that the getNextMessageFromQueue() keep to stay on the wait.
Am i locking the messages vars?
Thanks for your help.
My dispatcher class which send all messages to my clients :
private Vector<Message> messages = new Vector<Message>();
public synchronized void addMessage(Message message) {
messages.add(message);
notify();
}
private synchronized Message getNextMessageFromQueue() throws InterruptedException {
while (messages.size() < 1) {
wait();
}
Message message = (Message) messages.get(0);
messages.removeElementAt(0);
return message;
}
private void sendMessageToAllClients(Message message) {
for (int i=0; i < clients.size(); i++) {
Client client = (Client) clients.get(i);
client.sendMessage(message);
}
}
public void run() {
try {
while (true) {
Message message = getNextMessageFromQueue();
sendMessageToAllClients(message);
}
} catch (InterruptedException ie) {
ie.printStackTrace();
}
}
Here the client class :
private Socket socket;
private ObjectOutputStream out;
private ObjectInputStream in;
public Client(Socket s) throws IOException {
socket = s;
out = new ObjectOutputStream(socket.getOutputStream());
in = new ObjectInputStream(socket.getInputStream());
}
public Socket getSocket() {
return socket;
}
public void sendMessage(Message message) {
try {
out.writeObject(message);
out.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
Here is the main call of addMessage :
Message message = new Message();
message.setMessage("Welcome to " + client.getSocket().getLocalAddress() + ":" + client.getSocket().getPort());
dispatcher.addMessage(message);
I think you have a mistake in line in = new ObjectInputStream(socket.getInputStream());
Remove it, if it is not necessary or rebuild in other way. Read this Java sockets: Program stops at socket.getInputStream() w/o error?
To understand if your inputData is empty use - socket.getInputStream().available(), it returns size of input bytes.
Related
I'm developing a client server application in java. Communication takes place by serializing/deserializing immuable objects containing the information required, with ObjectOutputStream and ObjectInputStream.
In the server, every time I accept a new tcp connection, I instantiate a new Thread to handle the connection with that particular client.
This thread has a reference to the socket and it keeps reading objects:
while (true){
Object receivedObject = inputStream.readObject();
if (receivedObject instanceof MessageA){
//do sth
} else if (receivedObject instanceof MessageB){
//do sth else
}
this Runnable also has a method to send objects to the client:
public void sendMessage(Message message) {
try {
output.writeObject(message);
output.reset();
} catch (IOException e) {
e.printStackTrace();
}
}
client-side, when the user enters the server's address, I instantiate a SocketClient object to handle the communication with the server:
public class SocketClient extends Observable {
private final Socket socket;
private final ObjectOutputStream outputStream;
private final ObjectInputStream inputStream;
private static int TIMEOUT = 5000;
public SocketClient(String serverAddress, int serverPort) throws IOException {
this.socket = new Socket();
this.socket.connect(new InetSocketAddress(serverAddress, serverPort), TIMEOUT);
this.outputStream = new ObjectOutputStream(socket.getOutputStream());
this.inputStream = new ObjectInputStream(socket.getInputStream());
}
public void readMessage() {
Thread readerThread = new Thread(() -> {
boolean read = true;
while (read) {
Message message;
try {
message = (Message) inputStream.readObject();
notifyObservers(message);
} catch (IOException | ClassNotFoundException e) {
message = new ErrorMessage(null, "Connection lost with the server.");
disconnect();
read = false;
}
}
});
readerThread.start();
}
public void sendMessage(Message message) {
try {
outputStream.writeObject(message);
outputStream.reset();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
public void disconnect() {
try {
socket.close();
} catch (IOException e) {
// disconnection error
e.printStackTrace();
}
}
}
messages are sent and received in both applications, the only problem is that when I send multiple messages sequentially in the server, they are sometimes received in a different order in the clients.
How may I fix that?
In client socket, I wrote a thread to read the socket's inputStream continuously. Here I have used a while loop to read infinitely. However it takes more CPU; hence is it possible to reduce the CPU. Please add your suggestions.
Also is it possible to add listeners for inputStream.
Thread code:
public void run() {
while (!shutdown) {
try {
if(socketClient != null) {
String message = socketClient.getMessage();
logger.info ("Message size:" + message.length ());
if(!message.equals("EmptyString")) {
process(message);
}
}
} catch (Exception exception) {
logger.info("Unable to read the socket message" +exception);
}
}
}
SocketClient.java
public class SocketClient{
private volatile boolean isConnected;
private int port;
private int retryCount;
private long startTime;
private String hostName;
private DataInputStream input;
private DataOutputStream output;
private Socket socket;
public SocketClient(int port, String hostname) throws IOException {
this.port = port;
this.hostName = hostname;
establishConnection();
}
public void shutdown() {
try {
shutdown = true;
input.close();
output.close();
socket.close();
} catch (Exception e) {
logger.debug("Exception in shutdown:" + e.getMessage());
}
}
public String getMessage() {
BufferedReader reader = null;
try {
StringBuilder builder = new StringBuilder();
reader = new BufferedReader(new
InputStreamReader(tcpSocket.getInputStream()));
do {
builder.append(reader.readLine());
} while((reader.ready()));
if (builder.length() == 0)
return "EmptyString";
return builder.toString();
} catch (IOException e) {
return "EmptyString";
} finally {
try {
if(reader != null)
reader.close();
} catch(IOException e) {
logger.error("unable to close reader");
}
}
}
private void establishConnection() {
retryCount = 1;
startTime = System.currentTimeMillis();
while (!shutdown) {
try {
if(!isConnected) {
socket = new Socket(hostName,port);
socket.setKeepAlive(true);
input = new DataInputStream(socket.getInputStream());
output = new DataOutputStream(socket.getOutputStream());
isConnected = true;
shutdown = true;
}
} catch (Exception exception) {
isConnected = false;
sleepFewSeconds();
reconnectSocket();
}
}
}
private void reconnectSocket() {
long endTime = startTime + 120000L;
if(!(System.currentTimeMillis() < endTime)) {
shutdown = true;
}
}
private void sleepFewSeconds() {
try {
TimeUnit.MILLISECONDS.sleep(20);
} catch (InterruptedException interruptedException) {
shutdown = true;
}
}
}
I am going to critique the entire class here. The answer to your specific question will appear.
public class SocketClient{
private volatile boolean isConnected;
You don't need this. socket == null would do just as well.
private int port;
private int retryCount;
private long startTime;
private String hostName;
private DataInputStream input;
private DataOutputStream output;
private Socket socket;
public SocketClient(int port, String hostname) throws IOException {
this.port = port;
this.hostName = hostname;
establishConnection();
}
public void shutdown() {
try {
shutdown = true;
input.close();
output.close();
socket.close();
You don't need all these closes, and you're doing them in the wrong order anyway. output.close() is sufficient and in any case it should certainly be first.
} catch (Exception e) {
logger.debug("Exception in shutdown:" + e.getMessage());
}
}
public String getMessage() {
BufferedReader reader = null;
The BufferedReader should be an instance variable, not a local variable. It's buffered. If you make it a local variable you will lose data.
try {
StringBuilder builder = new StringBuilder();
reader = new BufferedReader(new
InputStreamReader(tcpSocket.getInputStream()));
do {
builder.append(reader.readLine());
} while((reader.ready()));
You don't need all this. If the message is a single line, all you need is return reader.readLine(), and you need the caller to check whether it was null, and if so close the socket, cease reading, etc. If the message is more than one line, this is a misuse of ready(): it is certainly not an indicator of end of message. It appears from comments under your question that you shouldn't even have the method: just connect the socket input stream directly to your XML parser and let it do the reading.
if (builder.length() == 0)
return "EmptyString";
Don't do this. Return "" or null. Don't make up new magic strings for your application to have to decode.
return builder.toString();
} catch (IOException e) {
return "EmptyString";
Ditto.
} finally {
try {
if(reader != null)
reader.close();
You should not close the reader here. Closing it will close the socket, so you can never get another message.
} catch(IOException e) {
logger.error("unable to close reader");
}
}
}
private void establishConnection() {
retryCount = 1;
startTime = System.currentTimeMillis();
while (!shutdown) {
try {
if(!isConnected) {
socket = new Socket(hostName,port);
socket.setKeepAlive(true);
input = new DataInputStream(socket.getInputStream());
output = new DataOutputStream(socket.getOutputStream());
isConnected = true;
shutdown = true;
Why are you setting shutdown to true here? Nothing is shutdown yet. It's a brand new socket.
}
} catch (Exception exception) {
isConnected = false;
sleepFewSeconds();
reconnectSocket();
}
Poor practice. Socket.connect(), which is called internally by new Socket(...), already retries, and also you should distinguish between connection-failure exceptions rather than adopt the same strategy for them all. For example, a 'connection timeout' will already have blocked for a minute or so: you don't need another sleep; and 'connection refused' means there is nothing listening, so retrying is completely pointless.
private void reconnectSocket() {
long endTime = startTime + 120000L;
if(!(System.currentTimeMillis() < endTime)) {
shutdown = true;
}
}
private void sleepFewSeconds() {
try {
TimeUnit.MILLISECONDS.sleep(20);
This is not a 'few seconds'. It is 20 milliseconds, and that is not enough by at least two orders of magnite in network programming, to the extent that there should be any sleep at all of course.
} catch (InterruptedException interruptedException) {
shutdown = true;
shutdown appears to be never false. I doubt that you've thought through what it really means, and I doubt that you really need it at all.
As for your calling code:
public void run() {
while (!shutdown) {
try {
if(socketClient != null) {
If socketClient is null this loop will spin meaninglessly. Surely this method should construct the socket client?
String message = socketClient.getMessage();
logger.info ("Message size:" + message.length ());
Here you are failing to check for null and failing to respond appropriately, which would be to close the socket and exit the loop. Instead you will get an NPE here.
if(!message.equals("EmptyString")) {
process(message);
See above. Don't send yourself special text messages. What happens if the peer needs to send that one day?
}
}
} catch (Exception exception) {
logger.info("Unable to read the socket message" +exception);
Unacceptable. This catch is inside the loop and it essentially ignores the exception. The result is that, again, this loop will spin meaninglessly on any exception. And the methods you're calling should be declared to throw IOException, and that is all you should catch here. At present you will spin even on NullPointerException.
I've been trying to make the code below to have multiple clients communicate with the same server.
Currently, it works one client at a time with the server but it seems to be that when the second client opens, code stops at new ObjectInputStream(connection.getInputStream()); in the Class 3 (client) - see below.
I've tried making the inputstream object transient to be shared in different threads but it didn't work, nor with making runClient method synchronized.
If I were to implement Serializable in the client class using serialVersionUID, how can I make multithreading work with the same server or is there any better way..?
Class 1 - server main
public class EchoServer {
private ServerSocket server;
private int portNum;
public static final int DEFAULT_PORT = 8081;
public EchoServer(int portNum) {
this.portNum = portNum;
}
public void runServer() {
System.out.println("Echo Server started...");
try {
server = new ServerSocket(portNum);
Socket connection = server.accept();
new Thread(new ClientHandler(connection)).run();
} catch(IOException ex) {
System.err.println("Error encountered! Port is likely already in use! Exiting program...");
ex.printStackTrace();
}
}
public static void main(String[] args) {
if (args.length > 0) {
(new EchoServer(Integer.parseInt(args[0]))).runServer();
} else {
(new EchoServer(DEFAULT_PORT)).runServer();
}
}
}
Class 2
public class ClientHandler implements Runnable {
private ObjectOutputStream output;
private ObjectInputStream input;
private String message;
/** Integer to hold the message number. */
private int messagenum;
private Socket connection;
public ClientHandler(Socket connection) {
this.connection = connection;
}
#Override
public void run() {
do{
handleRequest();
} while (true);
}
public void handleRequest() {
try {
output = new ObjectOutputStream(this.connection.getOutputStream());
input = new ObjectInputStream(this.connection.getInputStream());
do {
try {
message = (String) input.readObject();
System.out.println(messagenum +" Output> " +message);
} catch (EOFException | SocketException e) {
message = null;
}
if (message != null) {
output.writeObject(messagenum +" FromServer> " +message);
output.flush();
++messagenum;
}
} while (message != null);
input.close();
output.close();
this.connection.close();
} catch (IOException | ClassNotFoundException ex) {
System.err.println("Error encountered! Exiting program...");
ex.printStackTrace();
}
}
}
Class 3 - client main
public class EchoClient implements Serializable {
private static final long serialVersionUID = 1L;
private Socket connection;
private ObjectOutputStream output;
private transient ObjectInputStream input;
private String message = "";
private static String serverName;
public static final String DEFAULT_SERVER_NAME = "localhost";
private static int portNum;
BufferedReader keyboard = new BufferedReader(new InputStreamReader(System.in));
public EchoClient(String serverName, int portNum) {
this.serverName = serverName;
this.portNum = portNum;
}
public synchronized void runClient() {
try {
connection = new Socket(InetAddress.getByName(serverName), portNum);
output = new ObjectOutputStream(connection.getOutputStream());
input = new ObjectInputStream(connection.getInputStream());
do {
System.out.print("Input> ");
message = keyboard.readLine();
if (message != null){
output.writeObject(message);
output.flush();
message = (String) input.readObject();
System.out.println(message);
}
} while (message != null);
input.close();
output.close();
connection.close();
} catch (IOException ioException) {
ioException.printStackTrace();
} catch (ClassNotFoundException exception) {
exception.printStackTrace();
}
}
public static void main(String[] args) {
switch (args.length) {
case 2:
(new EchoClient(args[0], Integer.parseInt(args[1]))).runClient();
break;
case 1:
(new EchoClient(DEFAULT_SERVER_NAME, Integer.parseInt(args[0]))).runClient();
break;
default:
(new EchoClient(DEFAULT_SERVER_NAME, server.EchoServer.DEFAULT_PORT)).runClient();
}
}
}
Call server.accept() in the loop to accept multiple client connections as mentioned in the other answers. Start a new thread with the Thread.start method instead of Thread.run- What's the difference between Thread start() and Runnable run().
volatile boolean isRunning = true;
public void runServer() {
System.out.println("Echo Server started...");
try {
server = new ServerSocket(portNum);
while(isRunning) {
Socket connection = server.accept();
new Thread(new ClientHandler(connection)).start();
}
} catch(IOException ex) {
System.err.println("Error encountered! Port is likely already in use! Exiting program...");
ex.printStackTrace();
}
}
run server needs to wait for connections in a loop otherwise it will connect once and that is it. It needs to close its connections too. Clean up its threads. that's just in server main. I'm pretty sure this is a duplicate. So keep on researching
As said by efekctive, you need your server.accept() in a loop, else it will accept the first client and exit the program. So put these two lines in runServer() in a loop like this:
boolean isRunning = true;
while(isRunning){
Socket connection = server.accept();
new Thread(new ClientHandler(connection)).run();
}
I have been working with TCP server/client stuff for a while. I am actully good at UDP programming when it comes to connecting more than one user that is multiple clients. I tried to do the same on a TCP server that i made using Threads but whenever the Thread gets to this piece of code
String reader = (String)in.readObject();
an error is generated and the thread stops executing the code but the thread still runs the program keeping it alive.
Anyway here is the entire source code :
public class TestServer implements Runnable {
private Thread run, streams, connect, receive, send;
private ServerSocket socket;
private Socket conn;
private ObjectInputStream in;
private ObjectOutputStream out;
private boolean running, incomingMessage = false;
private int port;
public TestServer(int port) throws IOException {
this.port = port;
socket = new ServerSocket(port);
console("Server stated on : " + InetAddress.getLocalHost() + " : " + port);
run = new Thread(this, "Run");
run.start();
}
public void run() {
running = true;
connect();
receive();
}
private void connect() {
connect = new Thread("Connect") {
public void run() {
while(running) {
try {
conn = socket.accept();
} catch (IOException e) {
e.printStackTrace();
}
console("You are now connected" + conn.getInetAddress().toString() + " : " + conn.getPort());
try {
setupStreams();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}; connect.start();
}
private void setupStreams() throws IOException {
streams = new Thread("Streams") {
public void run() {
try {
console("Setting up Streams");
out = new ObjectOutputStream(conn.getOutputStream());
out.flush();
in = new ObjectInputStream(conn.getInputStream());
console("Streams are now setup");
incomingMessage = true;
receive.start();
} catch(IOException e) {
e.printStackTrace();
}
}
}; streams.start();
}
private void receive() {
receive = new Thread("Receive") {
public void run() {
while(incomingMessage) {
String message = "";
try {
message = (String) in.readObject();
//This is the only flaw the program
} catch (ClassNotFoundException | IOException e) {
e.printStackTrace();
}
console("Client : " + message);
}
}
};
}
private void console(String message) {
System.out.println(message);
}
public static void main(String[] args) {
try {
new TestServer(1234);
} catch (IOException e) {
e.printStackTrace();
}
}
}
FYI am not new to this. The error is caused because the server starts receiving packets even when there are no packets to be received. But because the thread forces it to receive it, i generates the error in the thread and dont know any other way to counter this. So please help. Thanks in Advance.
You shouldn't need 2 threads per connection. One thread is all that's required. After the connection is accepted, pass it to a worker thread to start reading. This can be done in a while loop in the worker thread.
Even though the socket's input stream can be read, the ObjectInputStream() class is more sensitive. If there is any error, its state is corrupted and it can't be used.
while (true) {
try {
Object input = in.readObject();
message = (String) input;
} catch (IOException e) {
e.printStackTrace();
break; //unrecoverable
} catch (ClassNotFoundException e) {
e.printStackTrace();
break; //unrecoverable
}
console("Client : " + message);
}
It's a better design to use a specific message protocol instead of sending serialized Java objects. For example if you are sending Strings like your sample, an InputStreamReader can be used to convert bytes to characters more easily and with less error handling.
These resources would be helpful to you:
https://docs.oracle.com/javase/tutorial/networking/sockets/clientServer.html#later
Java - Listening to a socket with ObjectInputStream
ObjectInputStream(socket.getInputStream()); does not work
I started learning networking with the main networking package in JDK, it's pretty simple and easy after a few examples. But now I am interested into making multi-client applications like a chat system.
My structure idea so far is like this:
Connection handler class, which handles incoming connections, and holds the list of clients.
If new connection was found, create a new client object, start it's thread (Client object will implement runnable, so it will start it's own looping service, it will loop for new packets received), and add it to the list.
I create a new thread for each client instead of looping through all clients because the reading from client process stops the whole execution and will wait for the client to send data, which is kinda annoys me and this is my issue there.
I have created a simple console app that receives messages from the client, but now I want to detect disconnections. I read that bufferedReader .read() method returns -1 if user is not connected, so I thought I could loop and do that every number of seconds to every client, but the thing is, the client must send a packet in order to .read() it, so let's say if you do .read() it will wait & stop the whole thread until packet is received, (I think).
This is my current code which gets messages from client:
public boolean isConnected() {
try {
this.in.read();
this.lastCheck = System.currentTimeMillis();
return true;
} catch (IOException e) {
if (!inConnection()) {
System.out.println("User disconnected");
try {
this.destruct();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
return false;
}
private boolean inConnection() {
return System.currentTimeMillis() - lastCheck < this.maxTime;
}
public void startClientService() throws IOException {
while(!this.session.isClosed()) {
if (System.currentTimeMillis() - this.checkTime > 600) {
System.out.println(System.currentTimeMillis() - this.checkTime);
if (this.isConnected()) {
int packetType = this.dataIn.readInt();
packets.getPacket(packetType);
}
}
}
}
public void destruct() throws IOException {
this.session.close();
this.connection.removeClient(this);
System.out.println("Session killed");
}
Basically what happens here, I am sending a integer packed from the client, I might have many things to do so therefore I can set many unique packet ID's, so if I want to receive and process a chat message, the packet id is 216, the client sends a int 216, server reads the packet, enters the switch loop of all packet ids and detects if its really 216, if yes it gets the instance of the packed class that handles messages & gets the bytes of the received message like this:
public class Chat implements Packet {
#Override
public void processPacket(Session c) {
String message = readMessage(c);
System.out.println("Message: " + message);
}
private String readMessage(Session c) {
byte[] data = c.readBytes();
String message = null;
try {
message = new String(data, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return message;
}
}
And this is how I read bytes:
public byte[] readBytes() {
int len;
byte[] data = null;
try {
len = this.dataIn.readInt();
data = new byte[len];
if (len > 0) {
this.dataIn.readFully(data);
}
} catch (IOException e) {
e.printStackTrace();
}
return data;
}
Okay my problem:
after adding the is disconnected detection, when I send my message, nothing happens. This is probably due to the .read() it stops and is waiting for a response. BUT if I write a message again, I will get the message in server.
This is my temporary, ugly client:
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket socket = new Socket("127.0.0.1", 43594);
Scanner r = new Scanner(System.in);
PrintWriter out = new PrintWriter(socket.getOutputStream());
String input;
while(true) {
input = r.next();
if (input != null) {
sendMessage(input, out);
}
}
}
public static void sendMessage(String message, PrintWriter out) {
byte[] encoded = encode(message);
out.write(0);
out.println(encoded + "\n");
out.flush();
}
public static byte[] encode(String s) {
return DatatypeConverter.parseBase64Binary(s);
}
public static String decode(byte[] s) {
return DatatypeConverter.printBase64Binary(s);
}
}
My question is: What is a better way of reading data from client without making the application wait for it and actually loop everytime? OR maybe should I have a new thread for checking if user is online so it's 2 threads per 1 client?
If someone needs my session object (client object):
public class Session extends Thread implements Runnable {
private Socket session;
private Client client;
private PrintWriter out;
private BufferedReader in;
private PacketHandler packets;
private DataInputStream dataIn;
private ConnectionHandler connection;
private final int checkTime = 1600;
private final int maxTime = 22000;
private long lastCheck;
public Session(Socket session) {
this.session = session;
this.client = new Client(this);
try {
this.setStream();
} catch (IOException e) {
e.printStackTrace();
}
this.packets = new PacketHandler(this);
System.out.println("[New session created]: " + session.getRemoteSocketAddress());
}
public void setConnectionHandler(ConnectionHandler c) {
this.connection = c;
}
public void run() {
try {
this.startClientService();
} catch (IOException e) {
e.printStackTrace();
}
}
public void setStream() throws IOException {
this.out = new PrintWriter(this.session.getOutputStream());
this.in = new BufferedReader(new InputStreamReader(this.session.getInputStream()));
this.dataIn = new DataInputStream(this.session.getInputStream());
}
public Client getClient() {
return this.client;
}
public byte[] readBytes() {
int len;
byte[] data = null;
try {
len = this.dataIn.readInt();
data = new byte[len];
if (len > 0) {
this.dataIn.readFully(data);
}
} catch (IOException e) {
e.printStackTrace();
}
return data;
}
public String readMessage() {
try {
return this.in.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
public boolean isConnected() {
try {
this.in.read();
this.lastCheck = System.currentTimeMillis();
return true;
} catch (IOException e) {
if (!inConnection()) {
System.out.println("User disconnected");
try {
this.destruct();
} catch (IOException e1) {
e1.printStackTrace();
}
}
}
return false;
}
private boolean inConnection() {
return System.currentTimeMillis() - lastCheck < this.maxTime;
}
public void startClientService() throws IOException {
while(!this.session.isClosed()) {
if (System.currentTimeMillis() - this.checkTime > 600) {
System.out.println(System.currentTimeMillis() - this.checkTime);
if (this.isConnected()) {
int packetType = this.dataIn.readInt();
packets.getPacket(packetType);
}
}
}
}
public void destruct() throws IOException {
this.session.close();
this.connection.removeClient(this);
System.out.println("Session killed");
}
}
Thanks!
While I don't have time to look over all the code, here are two things that could help you out.
1) Use a defined message header. Define X number of bytes of each message that the client will send to the server. Use these bytes to define how long the message will be, and what type of message it is. The server knows the length and layout of this header, and uses it to process the message in a particular way. Example could be a header of one byte. A value of 1 could be a I'm connected message. 2 could be I'm about to disconnect. 3 could be I'm currently away, and 4 could be an incoming chat message.
2) There are 2 ways you can handle the input. First is to use blocking IO, and create a separate thread to receive messages from each client. I believe this is what you are currently doing. The second is to use non-blocking IO, and have a separate thread iterate over the open sockets and do a read. Non-blocking will check if there is data to read, but if there is not, the thread will continue executing.