I have a server with multiple clients. It uses one server socket and two thread pools for receiving and handling requests from remote clients: one pool - for handling clients connections, and another one - for processing clients remote tasks. Each client sends asynchronous tasks with unique task ID (within each connection) and a bunch of parameters. Upon task deserialization, the server looks up the corresponding service, invokes the given method on it, wraps the result along with the task ID into the answer object and sends it back to the client using ObjectOutputStream.
Since tasks are handled concurrently, two or more threads might finish processing tasks for one client at the same time and try to compete for the ObjectOutputStream.
What happens next? I mean, do they write their objects to output stream atomically or should I synchronize their access to ObjectOutputStream, so that to avoid situation when one thread writes half of its object - then another thread intervenes and... as a result, a sort of Frankenstein object will be send to the client.
import java.io.*;
import java.lang.reflect.Method;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.*;
import java.util.concurrent.*;
public class Server {
private final ExecutorService connExecutor = Executors.newCachedThreadPool();
private final ExecutorService tasksExecutor = Executors.newCachedThreadPool();
public void start() {
try (ServerSocket socket = new ServerSocket(2323);) {
while (true) {
try (Socket conn = socket.accept()) {
connExecutor.execute(() -> {
try (ObjectInputStream in = new ObjectInputStream(conn.getInputStream());
ObjectOutputStream out = new ObjectOutputStream(conn.getOutputStream())) {
while (true) {
RemoteTask task = (RemoteTask) in.readObject();
tasksExecutor.execute(() -> {
handleTask(task, out);
});
}
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
});
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void handleTask(RemoteTask task, ObjectOutputStream out) {
RemoteAnswer answer = new RemoteAnswer();
// unwrap remote task
// lookup local service
// invoke task's method
// wrap result into remote answer
// send answer to the client
try {
out.writeObject(answer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
This here says it nicely:
Is writing an object to an ObjectOutputStream a thread-safe operation?
Absolutely not.
So, yes, your code needs to take precautions itself.
As a rule of thumb: If the documentation doesn't specify that a certain class is thread-safe, it probably isn't. Thread-safety clearly is an "intentional quality" (allusion to Roman Elizarov's blog post, one of Kotlin's language designers) and should therefore always be mentioned.
However, if you're still unsure whether a class of the Java SE-library provides thread-safety or not (as it might be mentioned somewhere else, e.g. the superclass' documentation), you might also just take a quick glance at the type's source code. As you can see, ObjectOutputStream doesn't implement any synchronization mechanisms.
Related
I am just keen to know whether it's possible to replace the old Multi threading codes written with Java's Executor service to Akka. I have few doubts regarding this.
Is akka actor runs in their own thread?
How Threads will be assigned for the Actors ?
What are the pros and cons of migration of it is possible?
Currently I use Fixed Thread pool for multi threading, and submit a callable.
Sample Code,
public class KafkaConsumerFactory {
private static Map<String,KafkaConsumer> registry = new HashMap<>();
private static ThreadLocal<KafkaConsumer> consumers = new ThreadLocal<KafkaConsumer>(){
#Override
protected KafkaConsumer initialValue() {
return new KafkaConsumer(createConsumerConfig());
}
};
static {
Runtime.getRuntime().addShutdownHook(new Thread(){
#Override
public void run() {
registry.forEach((tid,con) -> {
try{
con.close();
} finally {
System.out.println("Yes!! Consumer for " + tid + " is closed.");
}
});
}
});
}
private static Properties createConsumerConfig() {
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("group.id", "newcon-grp5");
props.put("key.deserializer", StringDeserializer.class.getName());
props.put("value.deserializer", KafkaKryoSerde.class.getName());
return props;
}
public static <K,V> KafkaConsumer<K,V> createConsumer(){
registry.put(Thread.currentThread().getName(),consumers.get());
return consumers.get();
}
}
/////////////////////////////////////////////////////////
import org.apache.kafka.clients.consumer.ConsumerRecord;
import org.apache.kafka.clients.consumer.ConsumerRecords;
import org.apache.kafka.clients.consumer.KafkaConsumer;
import org.apache.kafka.common.TopicPartition;
import org.apache.kafka.common.serialization.StringDeserializer;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
public class KafkaNewConsumer {
public static int MAX_THREADS = 10;
private ExecutorService es = null;
private boolean stopRequest = false;
public static void main(String[] args){
KafkaNewConsumer knc = new KafkaNewConsumer();
Runtime.getRuntime().addShutdownHook(new Thread(){
#Override
public void run(){
knc.es.shutdown();
try {
knc.es.awaitTermination(500, TimeUnit.MILLISECONDS);
} catch (InterruptedException ignored) {
}finally {
System.out.println("Finished");
}
}
});
knc.consumeTopic("rtest3",knc::recordConsuemer);
}
public void recordConsuemer(ConsumerRecord<?,?> record){
String result = new StringJoiner(": ")
.add(Thread.currentThread().getName())
.add("ts").add(String.valueOf(record.timestamp()))
.add("offset").add(String.valueOf(record.offset()))
.add("data").add(String.valueOf(record.value()))
.add("value-len").add(String.valueOf(record.serializedValueSize()))
.toString();
System.out.println(result);
}
public void consumeTopic(String topicName, Consumer<ConsumerRecord<?,?>> fun){
KafkaConsumer con= KafkaConsumerFactory.createConsumer();
int paritions = con.partitionsFor(topicName).size();
int noOfThread = (MAX_THREADS < paritions) ? MAX_THREADS :paritions;
es = Executors.newFixedThreadPool(noOfThread);
con.close();
for(int i=0;i<noOfThread;i++){
es.submit(()->{
KafkaConsumer consumer = KafkaConsumerFactory.createConsumer();
try{
while (!stopRequest){
consumer.subscribe(Collections.singletonList(topicName));
ConsumerRecords<?,?> records = consumer.poll(5000);
records.forEach(fun);
consumer.commitSync();
}
}catch(Exception e){
e.printStackTrace();
} finally {
consumer.close();
}
});
}
}
}
I went through some of the internet tutorial, some of them directly concludes
actors was very good and faster than traditional threads.
But no explanation how it can become faster than threads ?
I tried some sample Akka(Akka sample from activator) code, and printed Thread.currentThread.getName inside all actors and found different dispatcher threads named(helloakka-akka.actor.default-dispatcher-X) are created.
But how ? who is creating those threads ? where is the configuration for them ? What is the mapping relations between a thread and an Actor ?
Every time I send a message will Akka create new Thread? Or internally a Thread pool is used?
If I need 100 threads to do parallel execution of parts of the some task, do I need to create 100 Actors and send 1 message to each of them ? Or I need to create 1 actor and put 100 message in it's queue , It will get forked into 100 threads.
Really Confused
Migration to an actor system is not a small task for an executor based system but it can be done. It requires you to re-think the way you design the system and consider the impact of actors. For example in a threaded architecture you create some handler for a business process, toss it in a runnable and let it go off doing things on a thread. This is wholly inappropriate for an actor paradigm. You have to re-architect your system to deal with message passing and using the messaging to invoke tasks. Also you have to change the way you think about business processes from an imperative approach to a message based approach. Consider for the example the simple task of purchasing the product. I will assume you know how to do it in an executor. In an actor system you do this:
(Purchase Product) -> UserActor -> (BillCredit Card) -> CCProcessing Actor -> (Purchase Approved and Billed Item) -> inventory manager -> ... and so on
At each phase what is in the parentheses is an asynchronous message sent to the actor in question which performs business logic then forwards a message to the next actor in the process.
Now this is only one means of creating an actor based system, there are many other techniques but the core fundamental is you cant think imperatively but rather as a collection of steps that each run independently. Then the messages blast through the system at regular order but you cant be sure of the order or even if the message will get there so you have to design in semantics to handle that. In the system above I might have another actor checking every two minutes for orphaned orders that have not been presented to billing. Of course that means my messages need to ideimpotent to make sure if I send them the second time its ok, they wont bill the user twice.
I know I didn't deal with your specific example, I just wanted to provide some context for you that actors are not just another way to create an executor (well I suppose you could abuse them that way but its not advisable) but rather a completely different paradigm of design. A very worthwhile paradigm to learn for sure and if you make the leap you will never want to do executors ever again.
I face this problem in Java.
I have a server class named MyServer and I want to implement a thread pool where each thread runs a method of MyServer when a request comes. I have created another class that implements a server pool named MultiThreadedSocketServer. The class is this:
public class MultiThreadedSocketServer {
public void startServer(MyServer s, int localport, int threadPoolSize) {
final ExecutorService clientProcessingPool = Executors.newFixedThreadPool(threadPoolSize);
Runnable serverTask = new Runnable() {
#Override
public void run() {
try {
ServerSocket serverSocket = new ServerSocket(localport);
System.out.println("Waiting for clients to connect...");
while (true) {
Socket clientSocket = serverSocket.accept();
clientProcessingPool.submit(new ClientTask(clientSocket, s));
}
} catch (IOException e) {
System.err.println("Unable to process client request");
e.printStackTrace();
}
}
};
Thread serverThread = new Thread(serverTask);
serverThread.start();
}
}
the class named MultiThreadedSocketServer has an argument named Server s which passes it in client Task class which a thread is created. The client task class is this:
class ClientTask implements Runnable {
private final Socket clientSocket;
private MyServer s;
public ClientTask(Socket clientSocket, MyServer s) {
this.s = s;
this.clientSocket = clientSocket;
}
#Override
public void run() {
System.out.println("Got a client !");
String inputLine = null;
try {
BufferedReader in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
// Do whatever required to process the client's request
inputLine = in.readLine();
if (inputLine.equals("Bye")) {
System.out.println("Bye");
System.exit(0);
}
s.handleRequest(inputLine);
clientSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
As you can see when a request comes the handleRequest method of class MyServer is invoked. I want to make this method to run synchronized, meaning only one thread at a time to be able to run this method. Adding synchronized before the method implementation does not achieve anything.
Can anybody give me the proper way to do this?
Thanks in advance for your time.
PS: I added the whole code
MyServer Class
http://pastebin.com/6i2bn5jj
Multithreaded server Class
http://pastebin.com/hzfLJbCS
As it is evident in main I create three requests with handleRequest with arguments Task, task2 and Bye.
The correct output would be
Waiting for clients to connect...
Got a client !
This is an input Task
Request for Task
Got a client !
This is an input task2
Request for task2
Got a client !
This is an input
Bye
But Instead the order is mixed. Sometimes Bye which shuts the server can be executed first. I want to ensure that the order is the one where the requests are created in the main.
But Instead the order is mixed. Sometimes Bye which shuts the server can be executed first. I want to ensure that the order is the one where the requests are created in the main.
You say that you want the server to handle requests in order. This is hard to ensure because you are opening up 3 sockets and writing them to the server but not waiting for any response. This is implementation dependent but I'm not sure there is any guarantee that when the client returns from doing a socket InputStream write, that the server has received the bytes. This means that from the client side, there is no guarantee that the IO completes in the order that you want.
To see if this is the problem, I would remove the System.exit(0) to see if the other lines make it, just after the "Bye" string does. Or you could put a Thread.sleep(5000); before the exit(0).
A simple sort-of fix would be to make sure your PrintStream has auto-flush turned on. That at least will call flush on the socket but even then there are race conditions between the client and the server. If the auto-flush doesn't work then I'd have your client wait for a response from the server. So then the first client would write the first command and wait for the acknowledgement before going to the 2nd command.
In terms of your original question, locking on the server wouldn't help because of the race conditions. The "Bye" might make it first and lock the server fine.
These sorts of questions around how to synchronize the threads in a multi-threaded program really make no sense to me. The whole point of threads is that they run asynchronously in parallel and don't have to operate in any particular order. The more that you force your program to spit out the output in a particular order, the more you are arguing for writing this without any threads.
Hope this helps.
If the problem is that the bye message kills the server before other requests can be handled, one solution could be to not call System.exit(0); on bye.
The bye message could set a flag block further requests from being handled and also notify some other mechanism to call System.exit(0); when the thread pool is idle with no requests left to handle.
In Java, is there any way to call and handle asynchronous method inside a thread?
Consider an scenario in which one of the method inside thread body takes more time to execute it. Because of that, thread completion takes more time.
I have tried some examples by using concurrency package classes like FutureTask and Executors.
Is it possible to implement and handle all exceptions inside asynchronous method? and Is it possible to get success or error responses like AJAX success and error handlers in JavaScript?
How will we ensure that asynchronous method successfully executed or not (with or without parent thread context)?
Most natural way of communication between async method and parent thread is standard class CompletableFuture:
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
public class AsyncExample {
String input; // common data
// async method
public String toLower() {
return input.toLowerCase();
}
// method on main thread
public void run() {
input = "INPUT"; // set common data
try {
// start async method
CompletableFuture<String> future = CompletableFuture.supplyAsync(this::toLower);
// here we can work in parallel
String result = future.get(); // get the async result
System.out.println("input="+input+"; result="+result);
} catch (InterruptedException | ExecutionException e) {
}
}
public static void main(String[] args) {
new AsyncExample().run();
}
}
Note that creation and warming of an Executor, including the default executor used in the example, requires some time (50 ms on my computer), so you may want to create and warm one beforehand, e.g. by supplying an empty method:
CompletableFuture.supplyAsync(()->null).get();
Would it be appropriate to use a thread to get objects received by a socket's InputStream and then add them to a ConcurrentLinkedQueue so that they can be accessed from the main thread without blocking at the poll-input loop?
private Queue<Packet> packetQueue = new ConcurrentLinkedQueue<Packet>();
private ObjectInputStream fromServer; //this is the input stream of the server
public void startListening()
{
Thread listeningThread = new Thread()
{
public void run()
{
while(isConnected()) //check if the socket is connected to anything
{
try {
packetQueue.offer((Packet) fromServer.readObject()); //add packet to queue
} catch (ClassNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
};
listeningThread.start(); //start the thread
}
public Packet getNextPacket()
{
return packetQueue.poll(); //get the next packet in the queue
}
It depends on what you need to do with this object that you'll use in main thread.
If need sometime to process it or if it'll be used many times than you can put it in a queue or in another class that will hold this object for you, but if the time you need to process it is low you and you don't need this object further after processing you don't really need to use a queue.
About using the ConcurrentQueue depends too, you need order? you need guarantee synchronism between the read and the write?
You can use Asynchronous socket too to handle many clients and process in the same thread or even getting the objects from them and throwing in a queue to further process.
But "be appropriate" is hard to answer because depends on what you need to do with this objects and how you'll handle it.
I'm writing an android app in java and I want to create a listener that receive messages in a while(true) loop, and also to be able to send messages to the server.
For this task I'm using sockets with asyncTask.
I have written a connectionHandler class which handle all the send and receive requests for my app.
So far so good, everything is working fluently for just sending and receiving messages one at a time, but I just couldn't find a way to do it simultaneously.
I need to execute the following code in a thread, but I don't know how to do it, because I have to return a String:
public static String receive() {
try {
return mConnectionHandler.new AsyncReceiveFromServer().execute()
.get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
return null;
}
private class AsyncReceiveFromServer extends AsyncTask<Void, Void, String> {
#Override
protected String doInBackground(Void... params) {
String result = null;
try {
result = in.readLine();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
}
When I'm running the receive function in a while(true) loop, I can't send messages, because the ...execute().get() is blocking the java class connectionHandler.
So to sum up, how can I execute the above code in a thread or any other asynchronous way?
Or maybe you have any other suggestion to run the send and receive simultaneously while the receive is a while(true) loop?
First off- never use execute.get(). If you think you need to use it, you're architected wrong- it breaks the entire point of using a thread to have the calling thread wait for a result. If you just call execute, you'll run on another thread and work fine. If you need more than 1 thread running truly simultaneously, use executeOnExecutor() to override the 4.0 shared thread pool mechanism of AsyncTask.
Or better yet- don't use AsyncTask for this. You have something you want to run forever, waiting for input from a remote connection. This is a better fit for a Thread than an AsyncTask. I'd go with a thread and have the while loop built into the thread, and have the thread terminate only when the connection is closed.