I have the following code:
public static Client client = ClientBuilder.newClient();
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 100; i++) {
System.out.println(Thread.activeCount());
client.target("https://en.wikipedia.org/wiki/Special:Random").request().buildGet().submit(new InvocationCallback<Response>() {
#Override
public void completed(Response response) {
response.close();
}
#Override
public void failed(Throwable throwable) {
}
});
}
Thread.sleep(10000L);
System.out.println(Thread.activeCount());
}
Each time I call .submit() the client creates a new thread for the new get request that just permanently stays open. The problem with this is that I eventually reach the max # of threads and the program malfunctions because it cannot create a new thread. How do I avoid this problem?
Output:
1
2
3
4
...
101
The ideal solution would be to make this program single threaded and hang the program until each get-request receives a response. I'm open to using an alternative API if this is not possible with javax.ws.rs.
Related
I have got a server and client architecture that exchange information. I want to return from the server the number of connected channels. I want to return the message of the server to the clients using promise. My code is:
public static void callBack () throws Exception{
String host = "localhost";
int port = 8080;
try {
Bootstrap b = new Bootstrap();
b.group(workerGroup);
b.channel(NioSocketChannel.class);
b.option(ChannelOption.SO_KEEPALIVE, true);
b.handler(new ChannelInitializer<SocketChannel>() {
#Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new RequestDataEncoder(), new ResponseDataDecoder(), new ClientHandler(promise));
}
});
ChannelFuture f = b.connect(host, port).sync();
//f.channel().closeFuture().sync();
}
finally {
//workerGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
callBack();
while (true) {
Object msg = promise.get();
System.out.println("The number if the connected clients is not two");
int ret = Integer.parseInt(msg.toString());
if (ret == 2){
break;
}
}
System.out.println("The number if the connected clients is two");
}
When I run one client it is always receiving the message The number if the connected clients is not two and the returning number is always one. When I run a second client it is receiving always as a returning value two, however, the first client still is receiving one. I cannot find which is the correct way to update the promise for the case of the first client.
EDIT:
Client Server:
public class ClientHandler extends ChannelInboundHandlerAdapter {
public final Promise<Object> promise;
public ClientHandler(Promise<Object> promise) {
this.promise = promise;
}
#Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
RequestData msg = new RequestData();
msg.setIntValue(123);
msg.setStringValue("all work and no play makes jack a dull boy");
ctx.writeAndFlush(msg);
}
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println(msg);
promise.trySuccess(msg);
}
}
The code from the client handler storing the message received from server to the promise.
With the Netty framework, a Promise and a Future are write-once objects, this principle makes them easier to use in a multithreaded environment.
Since a Promise doesn't do what you want, we need to see if other technologies are fit for your conditions, your conditions basically boil down to:
Read from multiple threads
Write from a single thread only (as inside a Netty channel the read method can only be executed by 1 thread at the same time, unless the channel is marked shareable)
For these requirements, the best fitting match is a volatile variable, as this is thread-safe for reading, and can safely be updated by 1 thread without worrying about the write order.
To update your code for usage with a volatile variable, it requires some modifications, as we cannot easily pass the reference link to the variable inside your function, but we must pass a function that updates the backend variable.
private static volatile int connectedClients = 0;
public static void callBack () throws Exception{
//....
ch.pipeline().addLast(new RequestDataEncoder(), new ResponseDataDecoder(),
new ClientHandler(i -> {connectedClients = i;});
//....
}
public static void main(String[] args) throws Exception {
callBack();
while (true) {
System.out.println("The number if the connected clients is not two");
int ret = connectedClients;
if (ret == 2){
break;
}
}
System.out.println("The number if the connected clients is two");
}
public class ClientHandler extends ChannelInboundHandlerAdapter {
public final IntConsumer update;
public ClientHandler(IntConsumer update) {
this.update = update;
}
#Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
RequestData msg = new RequestData();
msg.setIntValue(123);
msg.setStringValue("all work and no play makes jack a dull boy");
ctx.writeAndFlush(msg);
}
#Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println(msg);
update.accept(Integer.parseInt(msg));
}
}
While the approach above should work, we quickly see that the while loop inside the main class uses a large share of CPU time, and this may affect other parts of your local client system, luckily, this problem is also solvable if we add other parts to the system, namely synchronization. By leaving the initial read of the connectedClients outside the synchronization block, we can still profit from the quick reads in the case of the "true" case, and in case of the "false' case, we can safe important CPU cycles that can be used in other parts of your system.
To tackle this problem, we use the following steps when reading:
Store the value of connectedClients in a separate variable
Compare this variable with the target value
If it's true, then break early out of the loop
If false, go inside a synchronized block
start a while true loop
Read out the variable again, since the value might be changed now
Check the condition, and break if condition is correct now
If not, wait for a change in the value
And the following when writing:
synchronize
Update the value
Wake up all other threads waiting for this value
This can be implemented in code as the following:
private static volatile int connectedClients = 0;
private static final Object lock = new Object();
public static void callBack () throws Exception{
//....
ch.pipeline().addLast(new RequestDataEncoder(), new ResponseDataDecoder(),
new ClientHandler(i -> {
synchronized (lock) {
connectedClients = i;
lock.notifyAll();
}
});
//....
}
public static void main(String[] args) throws Exception {
callBack();
int connected = connectedClients;
if (connected != 2) {
System.out.println("The number if the connected clients is not two before locking");
synchronized (lock) {
while (true) {
connected = connectedClients;
if (connected == 2)
break;
System.out.println("The number if the connected clients is not two");
lock.wait();
}
}
}
System.out.println("The number if the connected clients is two: " + connected );
}
Server side changes
However, not all of your problems are related to the client side.
SInce you posted a link to your github repository, you never send a request from the server back to the old clients when a new person has joined. Because this is not done, the client is never notified about the change, make sure to do this as well.
I have a piece of code that needs to make 15 requests in parallel then wait for all the requests to complete before proceeding.
Each request takes somewhere between 500-2500 ms. Is there a way in Java to get the time it takes for each future to complete the request?
I don't know of any built in methods in the Future api itself. However, if you use ListenableFutures, you can start a timer when you make the future and and stop the timer in the onSuccess or onFailure callback. Concretely, this could look something like:
public void timeRequests(MyRequests[] requestsToMake) {
ListeningExecutorService service = MoreExecutors.listeningDecorator(Executors.newFixedThreadPool(requestsToMake.length));
long startTimeNanos = System.nanoTime();
long[] endTimes= new long[requestsToMake.length]
for(int i =0; i < requestsToMake.length; i++){
MyRequest req = requestsToMake[i];
ListenableFuture<MyData> rFuture = service.submit(new Callable<MyRequest>() {
public MyData call() {
return req.makeRequest();
}
});
Futures.addCallback(rFuture, new FutureCallback<MyData>() {
public void onSuccess(MyData data) {
endTimes[i]=System.nanoTime();
//whatever else you do
}
public void onFailure(Throwable thrown) {
endTimes[i]=System.nanoTime();
//whatever else you do
}
});
}
I want to support both Synchronous and Asynchronous call using RESTEasy-JAXRS. And my asynchronous call should be based on callback, where Async request will have callbackURI, request gets processed asynchronously and upon completion makes a call to callbackURI with operation status/result. Can someone point me out to correct place? I see lot about polling model, but not callback with RESTEasy.
I am new to Asynchronous stuff...
Thanks in advance!
Thanks for your response rmlan.Yes but we have support in JAX-RS to handle asynchronous using #Suspended & AsyncResponse. I did that with following code, but i am unable to find the way to make callback to Client who called the API upon completion of task with this request.
#GET
#Path("/async")
public String checkAsync(#Suspended final AsyncResponse response) {
response.setTimeoutHandler(new TimeoutHandler() {
#Override
public void handleTimeout(AsyncResponse asyncResponse) {
response.resume(Response.status(Response.Status.SERVICE_UNAVAILABLE)
.entity("Operation time out.").build());
}
});
response.setTimeout(2, TimeUnit.SECONDS);
new Thread(new Runnable() {
#Override
public void run() {
String result = veryExpensiveOperation();
response.resume(result);
}
private String veryExpensiveOperation() {
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
logger.debug("Task is processed fully");
return "Successful";
}
}).start();
return "nothing";
}
Every method in class has one return ( or maybe void ) . but sometimes you need some callbacks from your method . this is the solution .
public abstract class MyClass {
public abstract void myCallbackMethod();
public void myMethod(){
for (int i = 0; i < 5; i++) {
// do somthing
myCallbackMethod();// it will implements in future.
}
}
}
when you make an object from MyClass , you must implement myCallbackMethod abstract method . like this
public class NewMain {
public static void main(String[] args) {
MyClass myClass=new MyClass() {
#Override
public void myCallbackMethod() {
System.err.println("this is call back");
}
};
myClass.myMethod();
}
}
and the result is
this is call back
this is call back
this is call back
this is call back
this is call back
it means you can get five call backs from void method in your class.
it is a good way when you do not have any idea for the body content of myCallBackMethod
the real example is download a file from server in your app .
you can call myCallBackMethod when bytes received and progress your progressbar
I have this 'Worker' class, which uses a resource 'Client'.
There may be any number of threads, running the 'Worker' at any given time.
The 'Client' is not thread-safe, thus I'm using 'ThreadLocal' for it.
The 'Client' connects to some server and executes a HTTP 'Request' that the worker feeds the 'Client'.
public class Worker {
// Client is NOT thread-safe !!!
private static ThreadLocal<Client> client = new ThreadLocal<Client>();
#Override
protected void onGet(Request req) {
handleRequest(req);
}
private void handleRequest(Request req) {
someRunnableExecutor(new Runnable() {
#Override
public void run() {
get_client().send_req(req);
}
});
}
private Client get_client() {
Client c = client.get();
if (c == null) {
c = new Client();
client.set(c);
}
return c;
}
At the current implementation (above), stripped down for clarity, there are as many "active" 'Clients' as there are running 'Workers'.
This is a problem because the server is being exhausted.
What I can do is only fix the 'Worker'. Have no access to the 'Client', server or the executor that runs the workers.
What I want to do is to have a Queue of 'Client'(s) and a piece of a synchronized code, in the 'Worker', that takes a 'Client' off the Queue, if the Queue is empty the 'Worker' should wait till there is one in the Queue for him to take. Then put the 'Client' back into the Queue - synchronized as well.
I really want to keep it as simple as possible, with the possible minimum changes made to the code.
No new classes, no factories, just some data structure to hold the 'Client'(s) and synchronization.
I am a bit puzzled with how to achieve that generally, as well as by the fact that the 'Client' is not thread-safe and that I have to 'ThreadLocal'(ize) it. Is this how do I put that in a Queue?
private static Queue<ThreadLocal<CLient>> queue =
new LinkedList<ThreadLocal<CLient>>();
Also, how/where do I initialize that Queue, once, with say 5 clients?
Please share your thoughts.
You don't need ThreadLocal here, as you want to have less Clients than Workers. All you need in BlockingQueue.
Notice! I supposed that Client's send_req is synchronous, if it's not - the code needs some changes in run() method
public class Worker {
private static final int CLIENTS_NUMBER = 5;
private static final BlockingQueue<Client> queue = new LinkedBlockingQueue<>(CLIENTS_NUMBER);
static {
for (int i = 0; i < CLIENTS_NUMBER; i++)
queue.put(new Client());
}
#Override
protected void onGet(Request req) {
handleRequest(req);
}
private void handleRequest(Request req) {
someRunnableExecutor(new Runnable() {
#Override
public void run() {
try {
Client client = takeClient();
client.send_req(req);
putClient(client);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
});
}
private Client takeClient() throws InterruptedException {
return queue.take();
}
private void putClient(Client client) throws InterruptedException {
queue.put(client);
}
}
Folks. I'm newbie in network programming and come across the following issue. I need to write the server which can maintain a connection with more than one client simultaneously. What I've written is the following:
Main class:
public class Main {
public static void main(String args[]) throws Exception{
ConnectionUtils.waitForClients();
}
}
ConnectionUtils class:
public class ConnectionUtils {
private static ServerSocket server;
static{
try {
server = new ServerSocket(54321);
} catch (Exception e) {
}
}
private static Runnable acceptor = new Runnable() {
#Override
public void run() {
try {
Client c = new Client(server.accept());
new Thread(acceptor).start();
c.sendLine("Hello client \n");
} catch (Exception e) {
}
}
};
public static void waitForClients(){
Thread clientAcceptor = new Thread(acceptor);
clientAcceptor.start();
}
}
and it works, more-or-less. But what is the downside of that approach? I suspect there're too much disadvantage, but I can't catch their.
The problem is that you creating an infinite number of threads where threads are expensive resources. You should be using a ThreadPool to limit the number of threads created in your program.
Consider using Executors instead of using this low-level code, In Oracle documentation about Executors, there is an example similar to what you doing. Check it out!
Heh interesting. I wouldn't expect it to be wrong but it sure isn't how I'd write it.
I'd probably have 1 thread in an infinite (semi-infinite with stop condition) loop that accepts and spawn threads, rather than something that looks like a recursive method but isn't. However as far as I can see it's not wrong.
Having said that, if you don't use your main thread for anything, why not do something like (and keep in mind i'm not a network programmer either)
public class ConnectionUtils {
protected boolean stop = false;
public static void waitForClients() {
while (!stop) {
Client c = new Client(server.accept());
new Thread(new ClientDelegate(c)).start();
}
}
}
public static class ClientDelegate implements Runnable {
private Client client;
public ClientDelegate(Client c) { this.client = c; }
public static void run() {
c.sendLine("Hello client\n");
}
}