BlockingQueue skips/loses elements - multithreading

Context:
As I understand, BlockingQueue is used to pass data between threads aka producer-consumer problem.
For example, in my case I use it to store received DatagramPackets so that other thread can process them. For now it just logs all incoming packets to a log file.
Here is the code I used to imitate the process:
Cons c = new Cons();
new Thread(c).start();
int i = 0;
byte[] databuf = new byte[1024];
DatagramPacket packet = new DatagramPacket(databuf, databuf.length);
try (DatagramSocket socket = new DatagramSocket(5555)){
while (10 < System.currentTimeMillis()) {
socket.receive(packet);
c.add(packet);
socket.send(new DatagramPacket("OK".getBytes(), "OK".getBytes().length, packet.getAddress(),
packet.getPort()));
}
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
}
Cons class handles writing to BlockingQueue and logging it in separate threads :
private static class Cons implements Runnable {
LinkedBlockingQueue<DatagramPacket> q = new LinkedBlockingQueue<>();
#Override
public void run() {
while (10 < System.currentTimeMillis()) {
try {
DatagramPacket packet = q.take();
logger.log(Level.INFO, "!" +"Message:" + new String(packet.getData(), packet.getOffset(),
packet.getLength()));
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public void add(DatagramPacket p) throws InterruptedException {
q.put(p);
}
Client side just sends set number of packets that this server receives.
Problem:
If thread that does reading from queue is somehow delayed, it starts to skip elements. In code example above it's imitated with Thread.sleep() but even logging alone is enough to make it skip few elements occasionally. And longer it takes for thread to request next element in queue more elements it skips. Using drainTo() provides same result.
In short, it rather behaives like single-element variable and not as queue. I don't understand why doesn't it just store all elements added so that handling thread can take them one-by-one and read?
Question:
Am I doing something wrong or is such behaviour intended?
Although now that I think about it, if even logging alone makes it so handler can't keep up with queue growing, how do I implement processing packets from multiple users? Do I have to create a different thread for each packet? That doesn't quite seems rational.

Related

CopyOnWriteArrayList is not working as expected

I am learning on CopyOnWriteArrayList and its not working as per my understanding.
I have two threads, one is main thread and another is inner thread. Main thread is removing the objects from the CopyOnWriteArrayList collection while inner thread is sleeping for 5 seconds. Main thread is completing the remove operations much before inner thread is iterating but inner thread is still iterating the full collection, I mean which are removed by main thread.
package com.kalavakuri.javaconcurrent;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
public class ConcurrentModificationExceptionExample {
private static List<String> strings = new CopyOnWriteArrayList<String>();
public static void main(String[] args) {
strings.add("Ram");
strings.add("Ravi");
strings.add("Raju");
strings.add("Raghu1");
strings.add("Raghu2");
strings.add("Raghu3");
strings.add("Raghu4");
strings.add("Raghu5");
strings.add("Raghu6");
Thread thread = new Thread(() -> {
Iterator<String> iterator = strings.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
System.out.println("Thread name " + Thread.currentThread().getName());
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "Inner thread");
thread.start();
Iterator<String> iterator = strings.iterator();
while (iterator.hasNext()) {
String value = iterator.next();
strings.remove(value);
System.out.println("Thread name " + Thread.currentThread().getName());
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
strings.forEach(v -> System.out.println(v));
}
}
I am expecting that inner thread should not iterate the objects which are removed by main thread. Correct me if my understanding is wrong.
Yes, you are wrong. From the docs:
The "snapshot" style iterator method uses a reference to the state of
the array at the point that the iterator was created. This array never
changes during the lifetime of the iterator, so interference is
impossible and the iterator is guaranteed not to throw
ConcurrentModificationException.
So by design the iterator will not change when the other thread makes changes.

Async technique in dropwizard

I have created a POST endpoint using DropWizard.
#POST
#Timed
public String runPageSpeed(#RequestParam String request) {
try {
JSONObject requestJSON = new JSONObject(request);
JSONArray urls = requestJSON.getJSONArray("urls");
process(urls); // this takes around 10 minutes to complete
return "done";
} catch (Exception e) {
throw new WebApplicationException("failed", Response.Status.INTERNAL_SERVER_ERROR);
}
}
process(urls); takes around 10 minutes to complete, so if we call this endpoint, it takes more than 10 minutes to get the response.
I want process(urls); to run in the background after receiving the URLs from the request and immediately return a response to the user.
I tried the following code using threads:
#POST
#Timed
public String runPageSpeed(#RequestParam String request) {
try {
JSONObject requestJSON = new JSONObject(request);
JSONArray urls = requestJSON.getJSONArray("urls");
Thread thread = new Thread() {
public void run() {
process(urls); // this takes around 10 minutes to complete
}
};
thread.start();
return "done";
} catch (Exception e) {
throw new WebApplicationException("failed", Response.Status.INTERNAL_SERVER_ERROR);
}
}
This works, but are there any issues if I use this approach, especially at a high volume?
DropWizard users should promote using CompletableFuture for async handling as it is the safest for handling background processing. With CompletableFuture you can move the heavyweight task to a background thread and simultaneously continue with the lightweight task thus can also send back a response to the client.
#POST
#Timed
public String runPageSpeed(#RequestParam String request) {
try {
JSONObject requestJSON = new JSONObject(request);
JSONArray urls = requestJSON.getJSONArray("urls");
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
try {
// perform heavyweight task
process(urls); // this takes around 10 minutes to complete
} catch (InterruptedException e) {
e.printStackTrace();
}
});
// perform lightweight task
return "done";
} catch (Exception e) {
throw new WebApplicationException("failed",
Response.Status.INTERNAL_SERVER_ERROR);
}
}
CompletableFuture helps in every aspects whether its using the return value of first complex task into second function or notifying on failure with the vast variety of methods it provides
runAsync()
supplyAsync()
thenApply()
thenAccept()
thenRun()
exceptionally()
handle()
You can also chain the CompletableFuture using thenCompose() and thenCombine() which is used when one task is dependent upon others.

Java servlet with threads send response to client

I have an HTML page with 3 input fields, when the user clicks the submit button, a AJAX request is made using jQuery to a servlet with the conetnts of the 3 fields.
When the requests arrives in the server (my servlet), I need to create a thread for each input field, and manage this thread pool, put them in order.
For example; If thread 1 finishes earlier, then thread 2 should print the response to the client, before the next thread. I'm currently using a sleep method in each thread with a random sleep time, to determine the time each thread should take.
On the client side, in the HTML, I've an element to show the response.
To send the information to the client, I just need to call PrintWriter.write on the servlet side.
The problem that I'm having is that the information of each thread appears at client side at the same time.
The output only appears on client side after all the threads have finished.
For example; I have thread a which took 200ms, a thread b which took 300ms, and a thread c which took 100ms.
The result on client side will only appear after 300ms, for example the result would be the string "cab".
So I have the following JavaScript function on my HTML page:
$.ajax({
type : 'get',
url : 'ServletResponse2',
data : {
"name1" : name1,"name2" : name2, "name3" : name3
},
success : function(xhr,data) {
console.log("xhr:"+xhr);
console.log("xhr text:"+xhr.responseText);
console.log("data:"+data);
console.log("data2:"+data.data);
$("#listResponse2").append("<li>" + xhr);
$("#listResponse2").append("</li>");
},
complete : function(xhr,data) {
response = xhr.responseText;
console.log("exception:"+response);
$("#listResponse").append("<li>" + response);
$("#listResponse").append("</li>");
},
error : function(e) {
console.log("exception:"+e);
}
});
Then, in the servlet, I have this get method calling a executor service, which calls a Class Worker Thread which implements Runnable:
protected void doGet(HttpServletRequest request,HttpServletResponse response)
{
ExecutorService executor= Executors.newFixedThreadPool(3);
PrintWriter out=null;
response.setCharacterEncoding("UTF-8");
String name1 = request.getParameter("name1");
String name2 = request.getParameter("name2");
String name3 = request.getParameter("name3");
String name="";
for (int i = 1; i < 4; i++) {
name=request.getParameter("name"+i);
try {
out = response.getWriter();
Runnable worker = new WorkerThread("" + name,response);
executor.execute(worker);
} catch (IOException e) {
e.printStackTrace();
}
}
executor.shutdown();
while (!executor.isTerminated()) {
}
System.out.println("Finished all threads");
out.print(name);
}
In the WorkerThread.java, I created a run() method which is writing the response for each servlet, I even used the out.flush() and response.flushbuffer() methods.
public class WorkerThread implements Runnable {
private String command;
PrintWriter out;
HttpServletResponse response;
public WorkerThread(String s,HttpServletResponse sresponse){
this.command=s;
this.response=sresponse;
}
#Override
public void run() {
System.out.println(Thread.currentThread().getName()+" Start. Command = "+command);
try {
out = response.getWriter();
out.write(command);
out.flush();
response.flushBuffer();
} catch (IOException e) {
e.printStackTrace();
}
processCommand();
System.out.println(Thread.currentThread().getName()+" End.");
}
private void processCommand() {
try {
Long time=(long)(Math.random() * 5000);
Thread.sleep(time);
System.out.println("Thread.getName():"+Thread.currentThread().getName()+"|comand:"+command+"|time:"+ time);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
#Override
public String toString(){
return this.command;
}
}
I also tried to use a Callabe in the executor service instead of a Runnable, but the result was the same. Can anyone tell me what I'm doing wrong, and why the result of the threads is arriving at the same time to the client?
Well no matter what you do in your servlet you are using HTTP protocol between a client, the browser and a server, the java application.
The protocole says : browser prepares and send a request, and the servers gets the request, and elaborates and send a response : one response per request.
The three threads write in the same reponse. Hopefully, your the 3 threads run one at a time and each write little to the response, if not you could have output of threads intermixed. And your servlet kindly waits the end of the threads to terminate, if not the servlet container would have closed the response before the threads have time to write anything.
You did not say what you were trying to achieve, I suppose you wanted to test asynchronous loading of information. For that you need multiple requests : one to initialize the operation, and one for each piece of information, the servlet using the session to register what it has transmitted and what remains, or the client side identifying the pieces it wants. But a detailed workthrough is far beyond what I can put in this answer ...
In fact when in a browser you see pages coming pieces by pieces it is exactly what happens : a first request for the HTML part, then optionally others for css, jsp, images, videos.

On servlet 3.0 webserver, is it good to make all servlets and filters async?

I am confused with Async feature introduced in Servlet 3.0 spec
From Oracle site (http://docs.oracle.com/javaee/7/tutorial/doc/servlets012.htm):
To create scalable web applications, you must ensure that no threads
associated with a request are sitting idle, so the container can use
them to process new requests.
There are two common scenarios in which a thread associated with a
request can be sitting idle.
1- The thread needs to wait for a resource to become available or process data before building the response. For example, an application
may need to query a database or access data from a remote web service
before generating the response.
2- The thread needs to wait for an event before generating the response. For example, an application may have to wait for a JMS
message, new information from another client, or new data available in
a queue before generating the response.
The first item happens a lot (nearly always, we always query db or call a remote webservice to get some data). And calling an external resource will always consume some time.
Does it mean that we should ALWAYS use servelt async feature for ALL our servelts and filter ?!
I can ask this way too, if I write all my servelts and filters async, will I lose anything (performance)?!
If above is correct the skeleton of ALL our servlets will be:
public class Work implements ServletContextListener {
private static final BlockingQueue queue = new LinkedBlockingQueue();
private volatile Thread thread;
#Override
public void contextInitialized(ServletContextEvent servletContextEvent) {
thread = new Thread(new Runnable() {
#Override
public void run() {
while (true) {
try {
ServiceFecade.doBusiness();
AsyncContext context;
while ((context = queue.poll()) != null) {
try {
ServletResponse response = context.getResponse();
PrintWriter out = response.getWriter();
out.printf("Bussiness done");
out.flush();
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
} finally {
context.complete();
}
}
} catch (InterruptedException e) {
return;
}
}
}
});
thread.start();
}
public static void add(AsyncContext c) {
queue.add(c);
}
#Override
public void contextDestroyed(ServletContextEvent servletContextEvent) {
thread.interrupt();
}
}

Threading in Spring

I'm trying to do some optimization in my code and would like to spawn a thread where I do a time consuming operation. During the implementation of that optimization I was running into an issue which was driving me crazy. I simplified the issue and created a test case for that specific issue: (I'm using SpringJUnit4ClassRunner so the transaction is properly started at the beginning of the testCRUD method)
Could someone help me understand why the foundParent is null in the thread ?
private Semaphore sema = new Semaphore(0, false);
private long parentId;
#Test
public void testCRUD() {
//create
DBParent parent = null;
{
parent = new DBParent();
parentDao.persist(parent);
parentId = parent.getId();
assertTrue(parentId > 0);
parentDao.flush();
}
(new Thread(
new Runnable() {
public void run()
{
System.out.println("Start adding childs !");
DBParent foundParent = parentDao.findById(parentId);
assertTrue(foundParent != null); //ASSERTION FAILS HERE !!!!
System.out.println("Releasing semaphore !");
sema.release();
System.out.println("End adding childs !");
}
})).start();
try {
System.out.println("Acquiring semaphore !");
sema.acquire();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
=============================EDITED===================================
As per one comment suggestion, I created a threadManager bean which spawn the thread. Here is the code of the threadManager:
public class ThreadManager {
#Transactional(propagation=Propagation.REQUIRES_NEW)
public void executeTask(String Name, Runnable task) {
(new Thread(task, Name)).start();
}
}
Then in the previous test, instead of staring the thread manually, I just post it in the thread manager like this:
#Autowired private ParentDao parentDao;
#Autowired private ThreadManager threadManager;
private Semaphore sema = new Semaphore(0, false);
private long parentId;
#Test
public void testCRUD() {
//create
DBParent parent = null;
{
parent = new DBParent();
parentDao.persist(parent);
parentId = parent.getId();
assertTrue(parentId > 0);
parentDao.flush();
}
threadManager.executeTask("BG processing...",
new Runnable() {
public void run()
{
System.out.println("Start adding childs !");
DBParent foundParent = parentDao.findById(parentId);
assertTrue(foundParent != null); //ASSERTION FAILS HERE !!!!
System.out.println("Releasing semaphore !");
sema.release();
System.out.println("End adding childs !");
}
});
try {
System.out.println("Acquiring semaphore !");
sema.acquire();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
Unfortunately this doesn't work either !!! :-(
The transaction context is bound to the thread. So the code in the spawned thread doesn't run in the same transaction context as the code in the initial thread. So, due to transaction isolation (the I in ACID), the spawned thread doesn't see what the initial thread's transaction is inserting in the database.
You can bind Spring transaction to a new thread, to run transactions & Hibernate/JPA access in it. But this has to be a different TX and JPA/HB session from other threads.
Spring code for OpenSessionInViewFilter, is a reasonable an example of how to bind Hibernate session to Spring's TX management. You can strip this down to fairly minimal code.
See:
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
OpenSessionInViewFilter.doFilterInternal() -- this is where it actually binds it
TransactionSynchronizationManager.bindResource()
TransactionSynchronizationManager.unbindResource()
TransactionSynchronizationManager.getResource()
In one project (IIRC) I wrapped this functionality into a 'ServerThreadHb' class, to setup & save previous thread-bindings on construction -- with a restore() method to be called in a finally block, to restore previous bindings.
For your posted code sample, there isn't much point in running work on a separate thread -- since you synchronously wait for the work to be done. However I assume you were planning to remove that constraint & extend that functionality.

Resources