CopyOnWriteArrayList is not working as expected - multithreading

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.

Related

Executor Service with void return type

Here I want to call n threads and execute my function padrDao.saveGuidanceDetails(sgd) which is a DAO method performing insert operation and return a long value as shown in below code.
Im using Callable, but it asks me to return some value but I'm not familiar with threads to use Runnable for the same job. Can someone pls validate if code is right or any modifications to be done? I feel code is wrong since there is a return statement inside callable and that will take me outside the main method for the first task itself.
int totalThreadsNeeded=listForguidanceItems.size();
ExecutorService executor = Executors.newFixedThreadPool(totalThreadsNeeded);
List<Callable<Void>> runnableTasks = new ArrayList<>();
final PriceLineItemsResultExt response1=response;
for(final ProductLineItemResultExt item: listForguidanceItems)
{
int counter=0;
final SavedGuidanceDetailsDto sgd=list.get(counter);
Callable<Void> task1 = new Callable() {
public Void call() {
if (sgd.hasGuidance())
{
if (response1.isSaveGuidance()) {
long guidanceDetailsId = padrDao.saveGuidanceDetails(sgd);
item.setGuidanceDetailsId(String.valueOf(guidanceDetailsId));
}
}
return null;
}};
counter++;
runnableTasks.add(task1);
}
try {
executor.invokeAll(runnableTasks);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
logger.info("Thread fail exception " + e);
}
executor.shutdown();
Pls suggest me modifications with the right code? Thanks in advance
To use Runnable you can simply replace these :
Callable<Void> task1 = new Callable() {
public Void call() {
...
With
Runnable task1 = new Runnable {
public void run() {
...
And with runnable you wouldn't have to return anything.
Of course you'd also need to modify you runnableTasks to be a List<Runnable> if tou still want to store these in a Collection (possibly not), and also change the way you submit them in the ExecutorService as :
executor.submit(your_Runnable_object)

BlockingQueue skips/loses elements

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.

ConcurrentHashMap remove issue

I have a class like this
import java.util.concurrent.*;
public class TestClass<V> {
private final ConcurrentMap<String, Future<V>> requests;
private final ExecutorService executorService;
public TestClass(final ExecutorService executorService) {
this.executorService = executorService;
this.requests = new ConcurrentHashMap<>();
}
public V submitRequest(String cacheKey, Callable<V> request) throws Exception {
final Future<V> task = getOrCreateTask(cacheKey, request);
final V results;
try {
results = task.get();
} catch (InterruptedException | ExecutionException e) {
throw new IllegalStateException(String.format("Exception while executing request for key '%s'", cacheKey),
e);
} finally {
//Nullpointer here
requests.remove(cacheKey);
}
return results;
}
private synchronized Future<V> getOrCreateTask(String key, Callable<V> request) {
if (requests.containsKey(key)) {
return requests.get(key);
} else {
final Future<V> newTask = executorService.submit(request);
requests.put(key, newTask);
return newTask;
}
}
}
but sometimes under heavy load server throws nullpointer on requests.remove(cacheKey). I have read final when not escaped by this in the constructor is write guaranteed. i.e. other threads can see what is going on with my requests map.
Not sure how do i fix efficiently? Does not like that idea of adding synchronised on the whole parent level method
I'm not actually sure the NPE is where you're identifying it is unless cacheKey is null, which you could check for. The concurrentmap is set correctly so the requests field should never be null. Nevertheless, this code is not correctly synchronized. You are attempting to perform two operations in getOrCreateTask() that while under the synchronized keyword are not correctly synchronized with the map because the map is interacted with in submitRequest when you remove the values.
What is likely happening is that between the check ConcurrentMap#containsKey and ConcurrentMap#get that another thread has removed the value from the cache (ConcurrentMap#remove).
Thread A: Check Contains "foobar" => true
Thread B: Remove "foobar"
Thread A: Call get("foobar") => null
Thread A: Calls Future#get on a null pointer, which then throws a NPE.
Since you control the concurrentmap you can know you'll never have null values. In that case you should instead just call the #get method and check if the returned value is null. This will prevent another thread from removing the value between a contains/get pair since you'll be only accessing the map through one atomic operation.

While modifying ArrayList with one thread and iterating it with another thread, it is throwing ConcurrentModificationException

I was trying below code.
public class IteratorFailFastTest {
private List<Integer> list = new ArrayList<>();
public IteratorFailFastTest() {
for (int i = 0; i < 10; i++) {
list.add(i);
}
}
public void runUpdateThread() {
Thread thread2 = new Thread(new Runnable() {
public void run() {
for (int i = 10; i < 20; i++) {
list.add(i);
}
}
});
thread2.start();
}
public void runIteratorThread() {
Thread thread1 = new Thread(new Runnable() {
public void run() {
ListIterator<Integer> iterator = list.listIterator();
while (iterator.hasNext()) {
Integer number = iterator.next();
System.out.println(number);
}
}
});
thread1.start();
}
public static void main(String[] args) {
// TODO Auto-generated method stub
IteratorFailFastTest tester = new IteratorFailFastTest();
tester.runIteratorThread();
tester.runUpdateThread();
}
}
It is throwing ConcurrentModificationException sometimes and at times running successfully.
What I don't understand is, since there are 2 different methods each containing one thread. They will execute one by one. When one thread finishes modifying the list, Thread 2 will start iterating.
I also referred to this link(Why no ConcurrentModificationException when one thread iterating (using Iterator) and other thread modifying same copy of non-thread-safe ArrayList), but it is different scenario.
So, Why is it throwing this exception? Is it because of threads?
Can somebody explain?
You are starting two threads and then doing no further synchronization.
Sometimes, both threads will be running at the same time, and you will get the CME. Other times, the first thread will finish before the second thread actually starts executing. In that scenario won't get a CME.
The reason you get the variation could well be down to things like load on your system. Or it could simply be down to the fact that the thread scheduler is non-deterministic.
Your threads actually do a tiny amount of work, compared to the overheads of creating / starting a thread. So it is not surprising that one of them can return from its run() method very quickly.

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