java multi threading issue ( same run time ) - java

I have socket server in Java and other side socket client in PHP
I want to process socket request from PHP in java in same time by multi-threading but java do it one by one , wait to finish first request and the start second one ,
here is my code in JAVA :
while (true) {
try {
clientSocket = serverSocket.accept();
int i = 0;
for (i = 0; i < maxClientsCount; i++) {
if (threads[i] == null) {
(threads[i] = new clientThread(clientSocket, threads)).start();
break;
}
}
if (i == maxClientsCount) {
PrintStream os = new PrintStream(clientSocket.getOutputStream());
os.println("Server too busy. Try later.");
os.close();
clientSocket.close();
}
} catch (IOException e) {
System.out.println(e);
}
}
class clientThread extends Thread {
public clientThread(Socket clientSocket, clientThread[] threads) {
this.clientSocket = clientSocket;
this.threads = threads;
maxClientsCount = threads.length;
}
public void run() {
int maxClientsCount = this.maxClientsCount;
clientThread[] threads = this.threads;
try {
in = new BufferedReader(new InputStreamReader(this.clientSocket.getInputStream()));
URL aURL = new URL(RecivedURL);
// start out put
System.out.println("host = " + aURL.getHost());
// end out put
the BOLD line is example of my output , but I want to start output of multi started request in same time in same time .. JAvA wait to finish a request in one time for my code ..

I don't see why you'd want more than two threads here.
If you want to process request one by one, you might spawn just one thread that just listens the requests and immediately responds to it by sending a "processing" or a "check back later" message. (call this a listener thread)
if a client is sent a "processing" response the connection is kept alive and another thread is spawned that responds to the client with the actual processed result of request. (call this a processing thread).
You could make the listener thread send a keep alive message to the client in queue or you could ask it to check back after a set period of time with a request. You could make the listener thread more sophisticated by setting up queues to decide when to subsequently respond to clients who were sent "check back later" message
From implementation POV, your main thread could be your listener thread and it could spawn a processing thread when it's time to process a request.

I assume that it's executed so fast that the last request is finished before the next one can be accepted.
For debug purposes try to add:
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
into the run method so you can easier check if it's really not running in parallel.

Related

JAVA multithreaded server sockets

Following is the code (JAVA) that accepts a client socket connection and assigns a thread to each connection.
ServerSocket m_ServerSocket = new ServerSocket();
while (true) {
java.util.Date today = Calendar.getInstance().getTime();
System.out.println(today+" - Listening to new connections...");
Socket clientSocket = m_ServerSocket.accept();
ClientServiceThread cliThread = new ClientServiceThread( clientSocket);
cliThread.start();
}
Suppose 5 clients are connected, hence 5 threads are running.
client 1: threadId 11
client 2: threadId 12
client 3 :threadId 13
client 4 :threadId 14
client 5 :threadId 15
Suppose one of the clients sends a message "kill-client1" , I to wish end client 1's connection and kill the thread with Id 11, something like this :
public void run() {
try {
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
PrintWriter out = new PrintWriter(new OutputStreamWriter(clientSocket.getOutputStream()));
while (running) {
String clientCommand = in .readLine();
if (clientCommand.equalsIgnoreCase("Kill-client1")) {
// end the connection for client 1 & kill it's corresponding thread 11
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
How can I achieve this ?
Just keep track of all client sockets and/or handling threads.
Map<Integer,Socket> clients=new HashMap<>();
while (true) {
java.util.Date today = Calendar.getInstance().getTime();
System.out.println(today+" - Listening to new connections...");
Socket clientSocket = m_ServerSocket.accept();
clients.put(generateNewClientId(),clientSocket);
ClientServiceThread cliThread = new ClientServiceThread( clientSocket);
cliThread.start();
}
And then if you simply do
{
if (clientCommand.equalsIgnoreCase("Kill")) {
Socket socket=clients.get(idToShutDown);// get required id somehow (from request??)
socket.close();
}
}
This will close given socket resulting in breaking in.readLine() in handling thread thus finishing thread.
If you keep track of threads, you can set "interrupt" flag and probe it in while condition so your handling thread will be able to finish work gracefully.
You could do that by storing your Threads into a thread-safe map (as it will be accessed by several threads concurrently) using the thread id as key
// Map that will contain all my threads
Map<Long, ClientServiceThread> threads = new ConcurrentHashMap<>();
// Add to the constructor the instance of the class that manage the threads
ClientServiceThread cliThread = new ClientServiceThread(this, clientSocket);
// Add my new thread
threads.put(cliThread.getId(), cliThread);
cliThread.start();
Then when a kill is launched
String clientCommand = in.readLine().toLowerCase();
if (clientCommand.startsWith("kill")) {
main.interrupt(Long.valueOf(clientCommand.substring(4).trim()));
}
Then in the main class your method would look like:
public void interrupt(long threadId) {
// Remove the thread from the map
ClientServiceThread cliThread = threads.remove(threadId);
if (cliThread != null) {
// Interrupt the thread
cliThread.interrupt();
}
}
Finally you will need to make your class ClientServiceThread sensitive to interruptions
try {
...
while (!Thread.currentThread().isInterrupted()) {
// My code here
}
} finally {
clientSocket.close();
}
Just terminate the loop:
while (running) {
String clientCommand = in .readLine();
if (clientCommand.equalsIgnoreCase("Kill")) {
running = false;
}
}
or:
while (running) {
String clientCommand = in .readLine();
if (clientCommand.equalsIgnoreCase("Kill")) {
break;
}
}
And don't forget to close the socket in finally block.
To stop the current thread, you close the socket, and return from the run() method:
if (clientCommand.equalsIgnoreCase("Kill")) {
clientSocket.close();
return;
}
EDIT:
To close another thread, you can, for example
share a thread-safe map of clientID-Thread entries between threads. When a new client connects, you store the Thread started for this client in this map
when a Kill-client1 command comes in, you get the Thread corresponging the "client1" key from the map, and call ìnterrupt() on this thread.
in each thread (for example, the client1 thread), at each iteration of the loop, you check what the value of Thread.currentThread().isInterrupted(). If it's true, then you close the connection, remove the thread from the shared map, and return from the run() method.
The key point is that you never kill another thread. You always request a thread to stop by interrupting it, and the thread checks the value of its interrupt flag to decide when and how it must stop.

How can I prevent my UDP keepalive from using 100% CPU?

I have a Runnable that watches for data to send out UDP as well as to send a keep alive every 10 seconds. The process is taking 100% CPU. I tried setting the thread to low priority but didn't seem to make any difference.
private Runnable keepAliveRunnable = new Runnable() {
long nextSend = 0;
byte[] sendData;
#Override
public void run() {
if(DEBUG)
System.out.println("Starting keepAlive.");
while (socket != null) {
synchronized (socketLock) {
try {
sendData = sendQueue.poll();
if (sendData != null) {
socket.send(new DatagramPacket(sendData, sendData.length,
InetAddress.getByName(Main.ipAddress), 10024));
} else if (nextSend < System.currentTimeMillis()) {
if(DEBUG && nextSend < System.currentTimeMillis())
System.out.println("Update keepAlive.");
// Send /xremote
socket.send(new DatagramPacket(("/xremote").getBytes(),
("/xremote").getBytes().length,
InetAddress.getByName(Main.ipAddress), 10024));
nextSend = System.currentTimeMillis() + keepAliveTimeout;
// Send /info
socket.send(new DatagramPacket(("/info").getBytes(),
("/info").getBytes().length,
InetAddress.getByName(Main.ipAddress), 10024));
}
} catch (IOException e) {
e.printStackTrace();
if(!e.getMessage().contains("Socket closed")) {
e.printStackTrace();
}
}
}
}
System.out.println("keepAliveRunnable ended.");
}
};
Make sendQueue a LinkedBlockingQueue, and use poll timeouts.
You are busy waiting, which essentially forces your app to keep running the same logic over and over instead of giving the CPU back to the system.
Don't count on your own implementation of checking the time, that is unreliable and can result in what you're seeing. Instead, use blockingQueue.poll(10, TimeUnit.SECONDS), which automatically handles returning the CPU to the system.
I made a few other changes to your code; I put the duplicated packet construction code in a separate method, and I wrapped the synchronization of the socket only when the socket is actually being used. Notice how much cleaner it is when you let the queue do the work for you.
while(socket != null) {
try {
sendData = sendQueue.poll(10, TimeUnit.SECONDS);
if (sendData != null) {
sendPacket(sendData);
} else {
sendPacket("/xremote".getBytes());
sendPacket("/info".getBytes());
}
} catch (IOException e) {
e.printStackTrace();
if (!e.getMessage().contains("Socket closed")) {
e.printStackTrace();
}
}
}
And here's sendPacket:
private static void sendPacket(byte[] data) throws UnknownHostException, IOException {
// Note, you probably only have to do this once, rather than looking it up every time.
InetAddress address = InetAddress.getByName(Main.ipAddress);
DatagramPacket p = new DatagramPacket(data, data.length, address, 10024);
synchronized(socketLock) {
socket.send(p);
}
}
You should add a Thread.sleep() at the bottom of your while loop, to slow down your loop. As is, you're busy-waiting and churning the CPU while you wait for the nextSend time to be reached. Thread.sleep() will actually pause the thread, allowing other threads and processes to use the CPU while this one sleeps.
Sleeping for a 10th of a second (100 milliseconds) should be a good amount of time to sleep between iterations of your loop, if your goal is to actually do work every 10 seconds.
There are more advanced techniques for dispatching work every so often, like ScheduledExecutorService, which you could also consider using. But for a small application the pattern you're using is fine, just avoid busy waiting.
I think rather than polling your sendqueue, its better to use semaphore signal and wait.
When a packet is inserted in sendqueue, call semaphore signal.
Use semaphore wait instead of call to sendqueue.poll().
I assume you have separate threads for pushing popping data from sendqueue.
This is standard consumer producer problem. https://en.wikipedia.org/wiki/Producer%E2%80%93consumer_problem
After digging through my code, I had realized that over time I had whittled down the number of processes sending data to 1 (duh) so I really didn't need the runnable as I could just send the data directly. I also set up a separate runnable and used ScheduledExecutor. I thought I would just put that here for other to see. Durron597's code is a little prettier but since I'm only sending two packs now I decided to just put the code together.
// In main
pingXAir();
private void pingXAir() {
System.out.println("Start keepAlive");
ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);
executorService.scheduleAtFixedRate(keepAliveRunnable, 0, 5, TimeUnit.SECONDS);
}
private Runnable keepAliveRunnable = new Runnable() {
#Override
public void run() {
synchronized (socketLock) {
try {
if (DEBUG)
System.out.println("Update keepAlive.");
// Send /xremote
socket.send(new DatagramPacket(("/xremote").getBytes(),
("/xremote").getBytes().length,
InetAddress.getByName(Main.ipAddress), 10024));
// Send /info
socket.send(new DatagramPacket(("/info").getBytes(),
("/info").getBytes().length,
InetAddress.getByName(Main.ipAddress), 10024));
} catch (IOException e) {
e.printStackTrace();
if (!e.getMessage().contains("Socket closed")) {
e.printStackTrace();
}
}
}
}
};

Permanent and persistent Socket connection in java

I've created a client-server connection, something like a chat system. Previously I was using a while loop on the client side, and it was waiting to read a message from the console every time (of course server has a while loop as well to serve forever). But now, I'm trying to first create a connection at the beginning of the session, and then occasionally send a message during the session, so to maintain a permanent and persistent connection.
Currently, without the while loop, the client closes the connection and I don't know how to find a workaround.
Here is the client code:
import java.net.*;
import java.io.*;
public class ControlClientTest {
private Socket socket = null;
// private BufferedReader console = null;
private DataOutputStream streamOut = null;
public static void main(String args[]) throws InterruptedException {
ControlClientTest client = null;
String IP="127.0.0.1";
client = new ControlClientTest(IP, 5555);
}
public ControlClientTest(String serverName, int serverPort) throws InterruptedException {
System.out.println("Establishing connection. Please wait ...");
try {
socket = new Socket(serverName, serverPort);
System.out.println("Connected: " + socket);
start();
} catch (UnknownHostException uhe) {
System.out.println("Host unknown: " + uhe.getMessage());
} catch (IOException ioe) {
System.out.println("Unexpected exception: " + ioe.getMessage());
}
String line = "";
// while (!line.equals(".bye")) {
try {
Thread.sleep(1000);
//TODO get data from input
// line = console.readLine();
line="1";
if(line.equals("1"))
line="1,123";
streamOut.writeUTF(line);
streamOut.flush();
} catch (IOException ioe) {
System.out.println("Sending error: " + ioe.getMessage());
}
// }
}
public void start() throws IOException {
// console = new BufferedReader(new InputStreamReader(System.in));
streamOut = new DataOutputStream(socket.getOutputStream());
}
}
And here is the Server code:
import java.awt.*;
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class ControlServer {
private Socket socket = null;
private ServerSocket server = null;
private DataInputStream streamIn = null;
public static void main(String args[]) {
ControlServer server = null;
server = new ControlServer(5555);
}
public ControlServer(int port) {
try {
System.out
.println("Binding to port " + port + ", please wait ...");
server = new ServerSocket(port);
System.out.println("Server started: " + server);
System.out.println("Waiting for a client ...");
socket = server.accept();
System.out.println("Client accepted: " + socket);
open();
boolean done = false;
while (!done) {
try {
String line = streamIn.readUTF();
// TODO get the data and do something
System.out.println(line);
done = line.equals(".bye");
} catch (IOException ioe) {
done = true;
}
}
close();
} catch (IOException ioe) {
System.out.println(ioe);
}
}
public void open() throws IOException {
streamIn = new DataInputStream(new BufferedInputStream(
socket.getInputStream()));
}
public void close() throws IOException {
if (socket != null)
socket.close();
if (streamIn != null)
streamIn.close();
}
}
I would like to summarize some good practices regarding the stability of TCP/IP connections which I apply on a daily basis.
Good practice 1 : Built-in Keep-Alive
socket.setKeepAlive(true);
It automatically sends a signal after a period of inactivity and checks for a reply. The keep-alive interval is operating system dependent though, and has some shortcomings. But all by all, it could improve the stability of your connection.
Good practice 2 : SoTimeout
Whenver you perform a read (or readUTF in your case), your thread will actually block forever. In my experience this is bad practice for the following reasons: It's difficult to close your application. Just calling socket.close() is dirty.
A clean solution, is a simple read time-out (e.g. 200ms). You can do this with the setSoTimeoutmethod. When the read() method timeouts it will throw a SocketTimeoutException. (which is a subclass of IOException).
socket.setSoTimeout(timeoutInterval);
Here is an example to implement the loop. Please note the shutdown condition. Just set it to true, and your thread will die peacefully.
while (!shutdown)
{
try
{
// some method that calls your read and parses the message.
code = readData();
if (code == null) continue;
}
catch (SocketTimeoutException ste)
{
// A SocketTimeoutExc. is a simple read timeout, just ignore it.
// other IOExceptions will not be stopped here.
}
}
Good practice 3 : Tcp No-Delay
Use the following setting when you are often interfacing small commands that need to be handled quickly.
try
{
socket.setTcpNoDelay(true);
}
catch (SocketException e)
{
}
Good practice 4 : A heartbeat
Actually there are a lot of side scenario's that are not covered yet.
One of them for example are server applications that are designed to only communicate with 1 client at a time. Sometimes they accept connections and even accept messages, but never reply to them.
Another one: sometimes when you lose your connection it actually can take a long time before your OS notices this. Possibly due to the shortcomings described in good practice 3, but also in more complex network situations (e.g. using RS232-To-Ethernet converters, VMware servers, etc) this happens often.
The solution here is to create a thread that sends a message every x seconds and then waits for a reply. (e.g. every 15 seconds). For this you need to create a second thread that just sends a message every 15 seconds. Secondly, you need to expand the code of good practice 2 a little bit.
try
{
code = readData();
if (code == null) continue;
lastRead = System.currentTimeMillis();
// whenever you receive the heart beat reply, just ignore it.
if (MSG_HEARTBEAT.equals(code)) continue;
// todo: handle other messages
}
catch (SocketTimeoutException ste)
{
// in a typical situation the soTimeout is about 200ms
// the heartbeat interval is usually a couple of seconds.
// and the heartbeat timeout interval a couple of seconds more.
if ((heartbeatTimeoutInterval > 0) &&
((System.currentTimeMillis() - lastRead) > heartbeatTimeoutInterval))
{
// no reply to heartbeat received.
// end the loop and perform a reconnect.
break;
}
}
You need to decide if your client or server should send the message. That decision is not so important. But e.g. if your client sends the message, then your client will need an additional thread to send the message. Your server should send a reply when it receives the message. When your client receives the answer, it should just continue (i.e. see code above). And both parties should check: "how long has it been?" in a very similar way.
You could wrap a thread around the connection and have it periodically send a status to keep the line open, say every 30 seconds or whatever. Then, when it actually has data to send it would reset the keep alive to be 30 seconds after the last transmission. The status could be helpful to see if the client is still alive anyway, so at least it can be a useful ping.
Also, you should change your server code, you appear to only handle one connection at the moment. You should loop and when a socket connection comes in spawn a thread to handle the client request and go back to listening. I may be reading to much into what may just be your test code, though.
Make the client socket connection wrapped around a thread. Use a blocking queue to wait for messages. There should only be a single sender queue throughout your application, so use a singleton pattern.
e.g.
QueueSingleton queue = QueueSingleton.getSenderQueue();
Message message = queue.take() // blocks thread
send(message); //send message to server
When you need to send a message to the server, you can use the blocking queue to send the message.
QueueSingleton queue = QueueSingleton.getSenderQueue();
queue.put(message)
The client thread will wake up and process the message.
For maintaining the connection, use a timer task. This is special type of thread that calls a run method repetitively at specified periods. You can use this to post a message, a ping message, every so often.
For processing the received message, you could have another thread, waiting for messages on another blocking queue (receiver queue). The client thread will put the received message on this queue.

Thread pool in a web server in Java

I have my multithread web server and now i wish to implement a thread pool, however even after looking about it i don't get how can i do it in my code :(
Could someone help me get it better?
I really need to understand how what i read can be used here, because i don't see the connection and how that works.
import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
public class WebServer {
static class RequisicaoRunnable implements Runnable {
private Socket socket;
RequisicaoRunnable(Socket socket) {
this.socket = socket;
}
#Override
public void run() {
try {
//System.out.println("connection from " + socket.getInetAddress().getHostName());
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//System.out.println("READING SOCKET...");
String str = in.readLine();
String[] arr = str.split(" ");
if (arr != null && arr.length > 2) {
while(!str.equals("")) {
//System.out.println(str);
str = in.readLine();
}
if (arr[0].equals("GET")) {
//System.out.println("REQUESTED RESOURCE: " + arr[1]);
String nomeArquivo = arr[1];
if (arr[1].startsWith("/")) {
nomeArquivo = nomeArquivo.substring(1);
}
if (nomeArquivo.equals("")) {
nomeArquivo = "index.html";
}
File f = new File(nomeArquivo);
if (f.exists()) {
FileInputStream fin = new FileInputStream(f);
socket.getOutputStream().write("HTTP/1.0 200 OK\n\n".getBytes());
byte[] buffer = new byte[1024];
int lidos;
do {
lidos = fin.read(buffer);
if (lidos > 0) {
socket.getOutputStream().write(buffer, 0, lidos);
}
} while (lidos > 0);
fin.close();
} else {
socket.getOutputStream().write("HTTP/1.0 404 Not Found\n\n".getBytes());
socket.getOutputStream().write("<html><body>HTTP/1.0 404 File Not Found</body></html>\n\n".getBytes());
}
} else {
socket.getOutputStream().write("HTTP/1.0 501 Not Implemented\n\n".getBytes());
}
}
socket.close();
} catch (IOException e) { }
}
}
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8080);
System.out.println("waiting connections....");
while (true) {
Socket socket = serverSocket.accept();
RequisicaoRunnable req = new RequisicaoRunnable(socket);
new Thread(req).start();
}
}
}
Idea behind the Thread pool is that create a specified number of threads at start and then assign task to them. Alternatively removing headache of creating threads each time.
I was implemented it a little some days ago, here is what I done.
Create some threads at start they share a request queue
Threads are constantly looking for queue and when a request come one
of the thread dispatch the request and perform action
The Queue will be synchronized 3.
Here are some queue methods
Queue#add(); //add the socket at the end
Queue#removeFront();//remove socket
Queue#isEmpty();//boolean if queue is empty
Queue#size(); //return size of queue
Queue#getMaxSize();//get maximum allowed size for queue
Your Request processing runnable
public class Processor implements Runnable {
private Queue<Socket> requests;
private boolean shut;
Processor(Queue<Socket> requests) {
this.requests = requests;
shut = false;
}
#Override
public void run() {
while(!shut) {
if(requests.isEmpty()) {
try{
Thread.sleep(#rendomeTimemill);
} catch(InterruptedException e){}
}else {
Socket skt = Queue.removeFront();
try {
//System.out.println("processing request from " + socket.getInetAddress().getHostName());
//do you want
} catch (Exception e) {
} finally {
if(skt != null) {
try{ skt.close(); skt = null; } catch(IOException ex){}
}
}
}
}
}
public void stopNow() {
shut = true;
Thread.interrupt();
}
}
in your main thread
create a queue to put requests
//start your server socket
Queue<Socket> requests = new Queue<Socket>();
Start worker thread pool
Precessor []workers = new Processor[NUM_WORKER];
for(int i=0;i<NUM_WORKER; i++) {
worker[i] = new Processor(requests);
Thread th = new Thread(worker[i]);
th.strat();
}
in request listening
//while loope that run forever
// accept socket
if(requests.size() == requests.getMaxSize()) {
socket.getOutputStream().write("HTTP/1.0 505 Error\n\n".getBytes());
socket.getOutputStream().write("<html><body>Try again</body></html>\n\n".getBytes());
socket.close();
} else {
requests.add(socket);
}
when you want to shout down server
for(int i=0;i<NUM_WORKER; i++) {
worker[i].stopNow();
}
Note: My concern was not the HTTP headers, so i m not specific, but you must implement the complete HTTP header e.g. Content-type, Content-length etc.
JDK might be a good place to start
An Executor or ExecutorService should is what you're looking for. Reading material:
http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html
The examples in there are pretty complete I think, but here's an example using the code you posted:
public static void main(String[] args) throws IOException {
ServerSocket serverSocket = new ServerSocket(8080);
System.out.println("waiting connections....");
ExecutorService pool = Executors.newCachedThreadPool();
while (true) {
Socket socket = serverSocket.accept();
RequisicaoRunnable req = new RequisicaoRunnable(socket);
pool.execute(req);
}
}
We create an executor service that is backed by a cached thread pool. You can swap this out for any type of pool you like by changing the type of executor service you get from Executors:
http://docs.oracle.com/javase/8/docs/api/java/util/concurrent/Executors.html
In the example I've given we use a cached thread pool which should create new threads as needed but re use old ones as they become available (finish whatever they were executing). If you look through the methods provided in that class you can create Executor services that are backed by various types of thread pool e.g. single thread, fixed number of threads, etc.
The example above should work as is, but if you want to change how the thread pool works try another thread pool type.
The cached thread pool will mean each connection will immediately be serviced, however it can create an unbounded number of threads.
on the other hand if you wanted the executor to use a blocking queue as suggested by fge you could try a fixed thread pool instead:
Executors.newFixedThreadPool(x)
you get the blocking queue for free with that.
You can use, for instance, a BlockingQueue. This is the basis for a producer/consumer scenario.
In your case:
the producer holds the server socket; it accepts new client sockets and pushes the client sockets onto the queue;
the consumers grab client sockets from the queue and process requests.
On top of all that, you can also use a bounded queue; you can try and push a new client socket to the queue; if the queue is full you can then default to a "no can't do" consumer.
Scenarios are many. There is not one answer.
OK, the idea is simple enough. You main loop currently creates a new RequisicaoRunnable object and a new Thread to run it each time it gets a connection from a client. The idea behind a thread pool is to avoid creating new Threads each time.
In the simplest version of a thread pool, you create a blocking queue, and you create and start a fixed number of worker threads before you enter your main loop. The main loop will look almost exactly the same as what you have now, but instead of starting a Thread to run each new RequisicaoRunnable, it will simply add the new object to the queue.
Your worker threads are all the same:
while (! shutdownHasBeenRequested()) {
RequisicaoRunnable requisicaoRunnable = getATaskFromTheQueue();
requisicaoRunnable.run();
}
That way, each new task (client) will be executed (handled) by the next available thread from your pool.
If this is a homework assignment then you'll pretty much want to implement what I described, filling in some details as needed.
If it's not homework, then consider using a java.util.concurrent.ThreadPoolExcecutor() instead. No point in re-inventing the wheel when there's a perfectly good wheel right there waiting to be used.
Edit: as fge said, one improvement would be to send back a quick "sorry, try again later" response when new connections are coming in faster than you can handle them. When the queue has too many pending connections in it (i.e., when you hit the limit of a BoundedQueue), that's when you know to bail out and send the "try again later" response.

java enter to another thread when using loop with sockets

I need a help I'm trying to make client server app for copying files in java... I've got MainWnd object which creates TCPServer object and on send button it will create TCPClient object which send initial data to opponent TCPServer and will open given number of Listen Thread (let it be n) (this Listen threads are here only because they accept a file) (every thread listen on different port which send back to TCPClient) TCPClient then creates n other TCPClients threads which send the file... This I've got and it's running. Problem is, that file receiving can be interrupted by receiver when he click on button Interrupt. I can't get information of this interruption to the receiver's TCPServer thread, which should kill this n threads which are downloading the file.
I think the problem is in TCPServer, where is infinit loop, but the Socket in this will cause blocking of loop so I can't enter to Connection class and kill this n threads.
TCP SERVER
public void setSendInterruption() {
this.interruptedSending = true;
//c.setSendInterruption();
}
public TCPServer(int port, int socketNums, Map<Byte, LinkedList<Byte>> realData, File file, int fileLength) {
this.serverPort = port;
this.socketNums = socketNums;
if(file != null)
this.file = file;
if(fileLength != -1)
this.fileLength = fileLength;
if(realData != null)
this.realData = realData;
if(tmpData != null)
this.tmpData = tmpData;
}
#Override
public void run() {
try {
System.out.println(this.getId());
listenSocket = new ServerSocket(serverPort);
System.out.println("server start listening... ... ...");
while(true) {
if(interruptedSending)
System.out.println("Here I never come");
Socket clientSocket = listenSocket.accept();
Connection c = new Connection(clientSocket, socketNums, realData, file, fileLength);
}
}
catch(IOException e) {
System.out.println("Listen :"+e.getMessage());}
}
Connection
while (true)
{
byteRead = input.read();
//Thread.sleep(100);
if(interruptedSending) {
TCPClient tcpClient = new TCPClient(clientSocket.getPort(), clientSocket.getInetAddress().getHostAddress());
tcpClient.sendInterruptedData();
interruptedSending = false;
}
char lowChar;
if(byteRead == -1) {
break;
} else
lowChar = (char)byteRead;
lowData += lowChar;
if(lowData.length() >= 2) {
if (lowData.substring(lowData.length()-2).compareTo("//") == 0) {
break;
} else if (lowData.length() > 6) {
byteData.add((byte)byteRead);
}
}
}
In connection there is more lines, but they are only mainly parsing a protocol.
Thanks a lof for your help. I hope I wrote it clean...
From what I understand each Connection has a Thread that runs it. You want to interrupt each of these threads but can't do that from within the threads because they are stuck in input.read().
If that is what you meant, just do this:
In the constructor of Connection save the Thread, so you can access it later.
Make a killThread()-Method or therelike, so you can access the thread from the outside:
public void killThread() {
thread.interrupt(); //thread is the thread you saved in the constructor
}
When you want to kill the Connection-thread call killThread(). This will cause the Thread to throw a java.lang.InterruptedException, wherever it is at the moment.
This one you can either ignore (since you want the thread to die anyways) or you encase the whole while-loop with a
try {
//your loop
} catch (InterruptedException e) {
return;
}
which will end the thread nicely without throwing the exception out.

Categories

Resources