I have gone through so many tutorials on Synchronization now that my head is spinning. I have never truly understood it :(.
I have a Java server(MainServer), that when a client connects creates a new thread(ServerThread) with a DataOutputStream.
The client talks to the ServerThread and the ServerThread responds. Every now and then the MainServer will distribute a message to all clients utilizing each ServerThread's DataOutputStream object.
I am quite certain that every now and then my issue is because both the MainServer and ServerThread are trying to send something to the client at the same time. Therefore I need to lock on the DataOutputStream object. For the life of me I cannot understand this concept any further. Every example I read is confusing.
What is the correct way to handle this?
ServerThread's send to client method:
public void replyToOne(String reply){
try {
commandOut.writeUTF(reply);
commandOut.flush();
} catch (IOException e) {
logger.fatal("replyToOne", e);
}
logger.info(reply);
}
MainServer's distribute to all clients method:
public static void distribute(String broadcastMessage){
for (Map.Entry<String, Object[]> entry : AccountInfoList.entrySet()) {
Object[] tmpObjArray = entry.getValue();
DataOutputStream temporaryCOut = (DataOutputStream) tmpObjArray[INT_COMMAND_OUT]; //can be grabbed while thread is using it
try {
temporaryCOut.writeUTF(broadcastMessage);
temporaryCOut.flush();
} catch (IOException e) {
logger.error("distribute: writeUTF", e);
}
logger.info(broadcastMessage);
}
}
I am thinking I should have something like this in my ServerThread class.
public synchronized DataOutputStream getCommandOut(){
return commandOut;
}
Is it really that simple? I know this has likely been asked and answered, but I don't seem to be getting it still, without individual help.
If this were me.....
I would have a LinkedBlockingQueue on each client-side thread. Then, each time the client thread has a moment of idleness on the socket, it checks the queue. If there's a message to send from the queue, it sends it.
Then, the server, if it needs to, can just add items to that queue, and, when the connection has some space, it will be sent.
Add the queue, have a method on the ServerThread something like:
addBroadcastMessage(MyData data) {
broadcastQueue.add(data);
}
and then, on the socket side, have a loop that has a timeout-block on it, so that it breaks out of the socket if it is idle, and then just:
while (!broadcastQueue.isEmpty()) {
MyData data = broadcastQueue.poll();
.... send the data....
}
and you're done.
The LinkedBlockingQueue will manage the locking and synchronization for you.
You are on the right track.
Every statement modifying the DataOutputStream should be synchronized on this DataOutputStream so that it is not concurrently accessed (and thus do not have any concurrent modification):
public void replyToOne(String reply){
try {
synchronized(commandOut) { // writing block
commandOut.writeUTF(reply);
commandOut.flush();
}
} catch (IOException e) {
logger.fatal("replyToOne", e);
}
logger.info(reply);
}
And:
public static void distribute(String broadcastMessage){
for (Map.Entry<String, Object[]> entry : AccountInfoList.entrySet()) {
Object[] tmpObjArray = entry.getValue();
DataOutputStream temporaryCOut = (DataOutputStream) tmpObjArray[INT_COMMAND_OUT]; //can be grabbed while thread is using it
try {
synchronized(temporaryCOut) { // writing block
temporaryCOut.writeUTF(broadcastMessage);
temporaryCOut.flush();
}
} catch (IOException e) {
logger.error("distribute: writeUTF", e);
}
logger.info(broadcastMessage);
}
}
Just putting my 2 cents:
The way I implement servers is this:
Each server is a thread with one task only: listening for connections. Once it recognizes a connection it generates a new thread to handle the connection's input/output (I call this sub-class ClientHandler).
The server also keeps a list of all connected clients.
ClientHandlers are responsible for user-server interactions. From here, things are pretty simple:
Disclaimer: there are no try-catches blocks here! add them yourself. Of course you can use thread executers to limit the number of concurrent connections.
Server's run() method:
#Override
public void run(){
isRunning = true;
while(isRunning){
ClientHandler ch = new ClientHandler(serversocket.accept());
clients.add(ch);
ch.start();
}
}
ClientHandler's ctor:
public ClientHandler(Socket client){
out = new ObjectOutputStream(client.getOutputStream());
in = new ObjectInputStream(client.getInputStream());
}
ClientHandler's run() method:
#Override
public void run(){
isConnected = true;
while(isConnected){
handle(in.readObject());
}
}
and handle() method:
private void handle(Object o){
//Your implementation
}
If you want a unified channel say for output then you'll have to synchronize it as instructed to avoid unexpected results.
There are 2 simple ways to do this:
Wrap every call to output in synchronized(this) block
Use a getter for output (like you did) with synchronized keyword.
Related
I have the following code in ServerConnectionManager:
public class ServerConnectionManager implements Runnable {
private DatagramPacket receivedPacket;
//some more things here
public ServerConnectionManager(DatagramPacket receivedPacket){
this.receivedPacket = receivedPacket;
System.out.println("Connection manager has been assigned a request");
System.out.println("The port of the request packet is "+receivedPacket.getPort());
try {
sendReceiveSocket = new DatagramSocket();
} catch (SocketException se) {
se.printStackTrace();
System.exit(1);
}
}
#Override
public void run() {
//DEBUGGING LINES HERE
System.out.println("The start method on connection manager works..");
System.out.println("Point A");
System.out.println("The port of the request packet is "+receivedPacket.getPort()); // the thread gets stuck here
System.out.println("Does this work..?"); //This line never gets printed
//some other stuff to be done here
}
}
And i have some code in the run method of some other threads that make use of ServerConnectionManager: Lets Call this Thread B
#Override
public void run() {
while(true){
try {
System.out.println("Waiting..."); // so we know we're waiting
receiveSocket.receive(receivePacket);
} catch (IOException e) {
System.out.print("Stopped Listening for some reason..");
//e.printStackTrace();
}
System.out.println("Server received something" );
//Constructor of ServerConnectionManager
ServerConnectionManager serverConnectionManager = new ServerConnectionManager(receivePacket);
Thread managerThread = new Thread(serverConnectionManager, "connectionManager ");
managerThread.start();
//some more stuff to be done
}
}
The problem is that I can not call any methods on receivedPacket from within ServerConnectionManager run method. However, I am able to call receivedPacket.getPort() from within the constructor of this ServerConnectionManager thread and it gives me an expected output. But it does not do anything from within run method. The last line ServerConnectionManager prints is "Point A". Nothing after that!! Please check my DEBUGGING comments around that area to get a better idea of what I am talking about.
I know I have provided alot of code. But I can not understand the problem at all. I have tried passing additional parameters(objects) from Thread B to the constructor of ServerConnectionManager. And I am able to access those from the run method of ServerConnectionManager. Its just the receivedPacket that does not work...
You need to create a new DatagramPacket per receive if you want to start a new thread to handle it. Otherwise one thread is synchronized on it during receive() while the other thread is trying to call getPort(). The design is invalid in any case, as the receive() will overwrite everything in the previously received datagram while the thread is trying to process it.
How can I add to the sending queue, for example I choose a file with JFileChooser and then send it in a new thread to the client, and I want to choose another and send it as well. What happens is that it sends the files simultaneously and the output on the client side is broken.
I'd like to be able to add to a "queue" of some sort, so that when the first file is sent, the server will start sending the next one.
A good aproach for socket communication between server->client, is to have 1 thread per client and have this thread reading from a java.util.concurrent.BlockingQueue. Such interface is ideal (just like all the java.util.concurrent objects) for managing multithreading concurrency.
The idea, is that the Server has a ClientThread like this:
class BroadCastThread extends Thread{
LinkedBlockingQueue<SendFileTask> bcQueue = new LinkedBlockingQueue<>();
#Override
public void run() {
while( true ){
try {
SendFileTask task = bcQueue.take();
task.sendFile();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
void addTask(SendFileTask rt) throws InterruptedException{
bcQueue.put(rt);
}
}
interface SendFileTask{
void sendFile() throws Exception;
}
And use this by adding tasks to you thread object:
BroadCastThread bct = new BroadCastThread();
bct.start();
//With lambda
bct.addTask(() -> {
//Send file code
});
//Without lambda
bct.addTask(new SendFileTask() {
#Override
void sendFile() throws Exception {
//Send file code
}
});
You can even store the Socket information with the thread, and pass it throw the task interface, if you want the sendFile method to receive it as parameter.
I've just got my feet wet with multi-threading and its really awesome. I find myself trying to figure out new ways I can use it make things better and I think I found one but I'm unsure how to design the program for this.
Here's the situation. I have a queue server that multiple clients consume and produce data to but to kick start the process I run a java program on to put some initial data for them to start. then my program is done and I have excess capacity on the queue server but nothing is really running on it. So I want to try to do some maintenance tasks, run a service, and do low priority stuff.I'm not sure how do that though. How do I design a program that does completely different tasks concurrently?
Typically I just wrap my programs in a while (true) loop and it does a single task and I realize I cannot do two while loops at the same time in the same process(maybe nested?). To show a simplified example, I put a bunch of code that runs a runnable(maybe it'll process a low priority queue) and a service that monitors a socket and replies back(I might want to add more depending on cpu usage). How do I get them all to work together? Is there a better way to design it(I know long term its probably better to run multiple java processes but right now I am just trying to manage a single file and I suspect there's a way to give the socket service a higher priority than processing the queue within the file but if they are both running in different files I don't know how to lower one over the other instead of them fighting for resources)?
Thanks and I'll edit this question if it turns out I'm explaining this totally wrong. But in a nutshell, I want it to provide a service to other systems(server socket, in the example) and when its idle I want it to do a few other tasks.
Example(if you understand what I'm asking this code may not be necessary to read):
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
public class multipleThreads {
private ServerSocket server;
private int port = 7777;
public void ServerSocketExample() {
try {
server = new ServerSocket(port);
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println("starting");
ServerSocketExample example = new ServerSocketExample();
example.handleConnection();
while (true) {
//monitor low low priority queue
}
}
public void handleConnection() {
System.out.println("Waiting for client message...");
//
// The server do a loop here to accept all connection initiated by the
// client application.
//
while (true) {
try {
Socket socket = server.accept();
new ConnectionHandler(socket);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
class ConnectionHandler implements Runnable {
private Socket socket;
public ConnectionHandler(Socket socket) {
this.socket = socket;
Thread t = new Thread(this);
t.start();
}
public void run() {
try
{
//
// Read a message sent by client application
//
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
String message = (String) ois.readObject();
System.out.println("Message Received: " + message);
//
// Send a response information to the client application
//
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject("Hi...");
ois.close();
oos.close();
socket.close();
System.out.println("Waiting for client message...");
} catch (IOException e) {
e.printStackTrace();
} catch (ClassNotFoundException e) {
e.printStackTrace();
}
}
}
class MonitorQueue implements Runnable{
#Override
public void run() {
// TODO Auto-generated method stub
//do work when stuff comes in the queue
}
}
I strongly recommend you take a look at this project: Java Concurrent Animated. I found this probably the best way to get my head around concurrency concepts in Java: it's animated, interactive, and you can just take one concept at a time and get a good understanding.
http://sourceforge.net/projects/javaconcurrenta/
Take a look at the java.util.concurrent package. It's full off goodies for doing exactly the kinds of things you describe.
In particular, check out the Executors factory class which lets you build Thread Pools that allow multiple tasks to be scheduled and run concurrently on any number of Threads you specify.
Oracle has some great tutorials on using Executors:
http://docs.oracle.com/javase/tutorial/essential/concurrency/executors.html
http://docs.oracle.com/javase/tutorial/essential/concurrency/exinter.html
Concurrency is hard, you can read Java Concurrency in Practice, but even the experts have difficulties.
Look for a training course in your area.
I would like to recommend Concurrency Specialist Courses which is based on Java Concurrency in Practice and endorsed by the author, Brian Goetz
I have a server listening data from clients. Once a client sends data, it will go into a thread. Thus, each thread has a data. revFeaturePoints is the data which the server receives from clients.
Each revFeaturePoints has a float array, I want to compute the Euclidean distance between different revFeaturePoints in different thread?
I do not know how can let one thread to access another revFeaturePoints in other threads?
Here is the code:
public class MyServer {
public static void main(String[] args) throws IOException{
ServerSocket serverSocket = null;
//bind a serverSocket to the port and listen
try{
serverSocket = new ServerSocket(8888);
System.out.println("Listening: 8888");
}catch(IOException e){
e.printStackTrace();
}
while(true)
new MyServerThread(serverSocket.accept()).start();
}
}
public class MyServerThread extends Thread{
//Create a socket for each client
private Socket socket = null;
private ObjectInputStream dataInputStream = null;
private ObjectOutputStream dataOutputStream = null;
private ArrayList<FeaturePointList> revFeaturePoints = null;
//constructor
public MyServerThread(Socket socket){
super("MyServerThread");
this.socket = socket;
}
#SuppressWarnings("unchecked")
public void run(){
try{
dataOutputStream = new ObjectOutputStream(socket.getOutputStream());
dataInputStream = new ObjectInputStream(socket.getInputStream());
System.out.println("ip: "+ socket.getInetAddress());
revFeaturePoints = (ArrayList<FeaturePointList>) dataInputStream.readObject();
}catch(IOException e){
e.printStackTrace();
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally{
if(socket!=null){
try{
socket.close();
}catch(IOException e){
e.printStackTrace();
}
}
if(dataInputStream!=null){
try{
dataInputStream.close();
}catch(IOException e){
e.printStackTrace();
}
}
if(dataOutputStream!=null){
try{
dataOutputStream.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
}
}
A simple way would be putting a synchronized method in MyServerThread that returns the data.
Another way of doing it would be to use a BlockingQueue and place the data result in a queue and taking the results from this as a producer-consumer pattern. See here for a way of doing this.
If your MyServerThread class stashes the data into a field, you can access that field from multiple instances of MyServerThread.
You can share the data among threads by using a shared structure and correct synchronization. For example, you could have a ConcurrentHashMap<'threadname', data> in MyServerThread where each thread puts its data and search for data in other threads.
That said, you should evaluate your architecture. If N threads have to check what the other N-1 threads are doing with data, you are preparing a recipe for performance disaster. Probably, what you would like to do is to create some layering in your architecture, where a number of ServerThreads are gathering the request and placing them in a concurrent shared structure (e.g queues). Then another set of workers are comparing and processing the data and producing results in a collaborative system. Have a look at the producer-consumer pattern.
[really a comment but won't fit ;)]
maasg's answer is quite correct in the general sense, but I believe you are right now looking at design difficulties and not Java threaded implementation per se.
You server (as is) fires off a disposable thread on each connect request, and this thread simply reads one object from the client and then closes the connection. The passed object is put in a (server thread) instance scoped object (which is duly garbage collected after you exit run()).
It is completely unclear -- and thus the impression that this is a design problem -- how you determine which 2 threads to compare, or for that matter, what guarantees you have that there will be (always) 2 concurrent threads to begin with.
Logically, you clearly have some domain specific association between a server thread and some meaningful matter in your domain. This relationship needs to be embodied in code, but first we need to understand what is this distinction and relationship.
Objects aren't 'in different threads'. Objects are members of other different objects, usually referenced via 'get' methods. Forget about the thread issue entirely, it is irrelevant. You just want to compare a member of object A with a member of object B. This is just business as usual.
I have created a threaded service the following way:
public class TCPClientService extends Service{
...
#Override
public void onCreate() {
...
Measurements = new LinkedList<String>();
enableDataSending();
}
#Override
public IBinder onBind(Intent intent) {
//TODO: Replace with service binding implementation
return null;
}
#Override
public void onLowMemory() {
Measurements.clear();
super.onLowMemory();
}
#Override
public void onDestroy() {
Measurements.clear();
super.onDestroy();
try {
SendDataThread.stop();
} catch(Exception e){
...
}
}
private Runnable backgrounSendData = new Runnable() {
public void run() {
doSendData();
}
};
private void enableDataSending() {
SendDataThread = new Thread(null, backgrounSendData, "send_data");
SendDataThread.start();
}
private void addMeasurementToQueue() {
if(Measurements.size() <= 100) {
String measurement = packData();
Measurements.add(measurement);
}
}
private void doSendData() {
while(true) {
try {
if(Measurements.isEmpty()) {
Thread.sleep(1000);
continue;
}
//Log.d("TCP", "C: Connecting...");
Socket socket = new Socket();
socket.setTcpNoDelay(true);
socket.connect(new InetSocketAddress(serverAddress, portNumber), 3000);
//socket.connect(new InetSocketAddress(serverAddress, portNumber));
if(!socket.isConnected()) {
throw new Exception("Server Unavailable!");
}
try {
//Log.d("TCP", "C: Sending: '" + message + "'");
PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream())),true);
String message = Measurements.remove();
out.println(message);
Thread.sleep(200);
Log.d("TCP", "C: Sent.");
Log.d("TCP", "C: Done.");
connectionAvailable = true;
} catch(Exception e) {
Log.e("TCP", "S: Error", e);
connectionAvailable = false;
} finally {
socket.close();
announceNetworkAvailability(connectionAvailable);
}
} catch (Exception e) {
Log.e("TCP", "C: Error", e);
connectionAvailable = false;
announceNetworkAvailability(connectionAvailable);
}
}
}
...
}
After I close the application the phone works really slow and I guess it is due to thread termination failure.
Does anyone know what is the best way to terminate all threads before terminating the application?
Addendum: The Android framework provides many helpers for one-off work, background work, etc, which may be preferable over trying to roll your own thread in many instances. As mentioned in a below post, AsyncTask is a good starting point to look into. I encourage readers to look into the framework provisions first before even beginning to think about doing their own threading.
There are several problems in the code sample you posted I will address in order:
1) Thread.stop() has been deprecated for quite some time now, as it can leave dependent variables in inconsistent states in some circumstances. See this Sun answer page for more details (Edit: that link is now dead, see this page for why not to use Thread.stop()). A preferred method of stopping and starting a thread is as follows (assuming your thread will run somewhat indefinitely):
private volatile Thread runner;
public synchronized void startThread(){
if(runner == null){
runner = new Thread(this);
runner.start();
}
}
public synchronized void stopThread(){
if(runner != null){
Thread moribund = runner;
runner = null;
moribund.interrupt();
}
}
public void run(){
while(Thread.currentThread() == runner){
//do stuff which can be interrupted if necessary
}
}
This is just one example of how to stop a thread, but the takeaway is that you are responsible for exiting a thread just as you would any other method. Maintain a method of cross thread communcation (in this case a volatile variable, could also be through a mutex, etc) and within your thread logic, use that method of communication to check if you should early exit, cleanup, etc.
2) Your measurements list is accessed by multiple threads (the event thread and your user thread) at the same time without any synchronization. It looks like you don't have to roll your own synchronization, you can use a BlockingQueue.
3) You are creating a new Socket every iteration of your sending Thread. This is a rather heavyweight operation, and only really make sense if you expect measurements to be extremely infrequent (say one an hour or less). Either you want a persistent socket that is not recreated every loop of the thread, or you want a one shot runnable you can 'fire and forget' which creates a socket, sends all relevant data, and finishes. (A quick note about using a persistent Socket, socket methods which block, such as reading, cannot be interrupted by Thread.interrupt(), and so when you want to stop the thread, you must close the socket as well as calling interrupt)
4) There is little point in throwing your own exceptions from within a Thread unless you expect to catch it somewhere else. A better solution is to log the error and if it is irrecoverable, stop the thread. A thread can stop itself with code like (in the same context as above):
public void run(){
while(Thread.currentThread() == runner){
//do stuff which can be interrupted if necessary
if(/*fatal error*/){
stopThread();
return; //optional in this case since the loop will exit anyways
}
}
}
Finally, if you want to be sure a thread exits with the rest of your application, no matter what, a good technique is to call Thread.setDaemon(true) after creation and before you start the thread. This flags the thread as a daemon thread, meaning the VM will ensure that it is automatically destroyed if there are no non-daemon threads running (such as if your app quits).
Obeying best practices with regards to Threads should ensure that your app doesn't hang or slow down the phone, though they can be quite complex :)
Actually, you don't need the "runner" variable as described above, something like:
while (!interrupted()) {
try {
Thread.sleep(1000);
} catch (InterruptedException ex) {
break;
}
}
But generally, sitting in a Thread.sleep() loop is a really bad idea.
Look at the AsyncTask API in the new 1.5 API. It will probably solve your problem more elegantly than using a service. Your phone is getting slow because the service never shuts down - there's nothing that will cause the service to kill itself.