Java Mulithreaded CopyONWriteArrayList - java

I want to use data structure which can be constantly accesed by multithreaded code . Please let me know any Data structure in java , where I can wait and use notify options . Kindly see the below code , why run method of CDRemove doesnot print all values
public class ConcurrencyDemo {
public static void main(String[] args) throws InterruptedException {
CopyOnWriteArrayList<String> threadSafeList = new CopyOnWriteArrayList<String>();
CDInsert cd1 = new CDInsert(threadSafeList);
CDRemove cr1 = new CDRemove(threadSafeList);
cd1.start();
cr1.start();
}
}
class CDInsert extends Thread
{
List threadSafeList;
public CDInsert(List threadSafeList) {
this.threadSafeList = threadSafeList;
}
public void run()
{
int counter = 0;
while(counter < 20){
counter++;
threadSafeList.add(String.valueOf(counter));
System.out.println("Counter value is "+counter);
}
}
public void showItem(){
Iterator<String> failSafeIterator = threadSafeList.iterator();
while(failSafeIterator.hasNext()){
System.out.printf("Read from CopyOnWriteArrayList : %s %n", failSafeIterator.next());
}
}
}
class CDRemove extends Thread {
List threadSafeList;
public CDRemove(List threadSafeList) {
this.threadSafeList = threadSafeList;
}
public void run(){
Iterator<String> failSafeIterator = threadSafeList.iterator();
System.out.println("Fail Safe Iterator is "+failSafeIterator);
while(true){
System.out.println("Fail Safe Iterator is "+failSafeIterator);
while(failSafeIterator.hasNext()){
System.out.printf("Read from CopyOnWriteArrayList : %s %n", failSafeIterator.next());
}
}
}
}

thread CDRemove has an infinite loop:
while(true){ // Change this.
while(failSafeIterator.hasNext()){
System.out.printf("Read from CopyOnWriteArrayList : %s %n", failSafeIterator.next());
}
}
Now the iterator will represent the state of the list when constructed. If the CDInsert thread was still running, the iterator would not have all the elements.

Related

Thread is always running, can't stop

I want to make a test, two thread, one thread is changing the value, another thread use a while to wait the first thread, and then break and finish.But the question is the waiting thread is always running, can' stop any more. Another question is when i open the code of "System.out.println(i + " run");", all the thread can work normally, it's so strange.
import java.util.Date;
public class ThreadTestTwo {
public int a = 0, b = 0,c = 0;
public static void main(String[] args) {
System.out.println(new Date()+"start");
for (int i = 0; i < 100000; i++) {
new ThreadTestTwo().start(i);
if(i % 100000 == 0){
System.out.println(i/100000);
}
}
System.out.println(new Date()+"finish");
}
public void start(final int i){
Thread readThread = new Thread(){
#Override
public void run() {
while (true) {
if(c == 1){
b = a;
// System.out.println(i+", set b "+a);
break;
}
// System.out.println(i + " run");
}
}
};
Thread writeThread = new Thread(){
#Override
public void run() {
a = 1;
c = 1;
}
};
writeThread.setName("mywrite");
readThread.setName("myread");
System.out.println(i+" start");
writeThread.start();
readThread.start();
try {
writeThread.join();
readThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(i+" end");
if(b != 1)
throw new RuntimeException("b = "+b);
}
}
The writes of one thread are NOT guaranteed to be seen for another thread unless the variables are marked as volatile or otherwise the transactions need to handled using synchronization or explicit locking
In your case, a,b,c are the instance variables accessed by multiple threads and the reader thread caches the values and so it doesn't see the writer thread's flushed value.
Please refer the below link for more details:
https://docs.oracle.com/javase/tutorial/essential/concurrency/atomic.html
I advise you to read more on Threads. Here it is an interesting document from O'really: http://chimera.labs.oreilly.com/books/1234000001805/ch09.html
As for your implementation, you should be aware that the modification of one variable by a thread may not be seen by a reader thread. To combat that either use synchronised gets and sets, access the variables inside a synchronized block, or use an AtomicReference. You could also use a Lock such as ReantrantLock.
Also, if you have two threads, in which the first is waiting for the input of the second, you could use the wait() inside a synchronized block for the first, so that the second could notify() the first one when it finishes its job.
Something like this:
import java.util.Date;
public class ThreadTestTwo {
private int a = 0, b = 0,c = 0;
private final Object lock = new Object();
//Any object is good as a lock, and for a simple case as this it's fine.
//This object will work as a monitor for the synchronized blocks.
public void start(final int i){
Thread readThread = new Thread(){
#Override
public void run() {
synchronized ( lock ) {
try {
while( c != 1 ) {
lock.wait();
}
}
catch ( InterruptedException ex ) {
//Exception handling
}
b = a;
}
//System.out.println(i + " run");
}
};
Thread writeThread = new Thread(){
#Override
public void run() {
synchronized ( lock ) {
a = 1;
c = 1;
lock.notify();
}
}
};
writeThread.setName("mywrite");
readThread.setName("myread");
System.out.println(i+" start");
writeThread.start();
readThread.start();
System.out.println(i+" end");
}
public static void main(String[] args) {
System.out.println(new Date()+"start");
for (int i = 0; i < 100000; i++) {
new ThreadTestTwo().start(i);
if(i % 100000 == 0){
System.out.println(i/100000);
}
}
System.out.println(new Date()+"finish");
}
}
I would say you don't need join() with this method. But if want to wait for the second thread to start after the first is finished, you have to use join() before starting it. Like this:
writeThread.start();
try {
writeThread.join();
}
catch ( InterruptedException ex ) {
//Exception handling
}
readThread.start();
try {
readThread.join();
}
catch ( InterruptedException ex ) {
//Exception handling
}
But if you use join(), for this particular case, I would say you wouldn't need any synchronized blocks or conditions, since the second thread would only start after the death of the first one. Something like this:
public void start(final int i){
Thread readThread = new Thread(){
#Override
public void run() {
b = a;
//System.out.println(i + " run");
}
};
Thread writeThread = new Thread(){
#Override
public void run() {
a = 1;
c = 1;
}
};
writeThread.setName("mywrite");
readThread.setName("myread");
System.out.println(i+" start");
writeThread.start();
try {
writeThread.join();
}
catch ( InterruptedException ex ) {
//Exception handling
}
readThread.start();
try {
readThread.join();
}
catch ( InterruptedException ex ) {
//Exception handling
}
System.out.println(i+" end");
}
I hope I have helped.
Have a nice day. :)
It's not a good idea to use an simple int as a signal between threads because it's not thread safe.
So try to use AtomicInteger instead or make your int volatile and see what will happen.

How can iterate over and modify this Arraylist?

I have an arrayList which I am sharing between two threads and I am trying to iterate over and modify the list at the same time. I don't want to use the iterator's method, and I have also used the synchronized list but it still gives concurrentmodificationexception.
code is as follows :
public class testing {
public static void main(String args[]){
ArrayList<String> al = new ArrayList<String>();
List<String> sal=Collections.synchronizedList(al);
String names[] = {"amol","Robin","vikas","shanu","mahesh"};
for(String x :names){
al.add(x);
}
Thread t1 = new Thread(new SyncArrayList(sal));
Thread t2 = new Thread(new SyncArrayList(sal));
t1.setName("T1");
t2.setName("T2");
t1.start();
t2.start();
}
}
class SyncArrayList implements Runnable
{
List<String> unsync ;
SyncArrayList(List<String> l){
this.unsync = l;
}
#Override
public void run() {
displayUnsyncList();
addNames();
}
void displayUnsyncList(){
synchronized(this){
ListIterator<String> itr = unsync.listIterator();
while(itr.hasNext()){
String x = itr.next();
System.out.println("Thread " +Thread.currentThread().getName() + " is displaying name : "+x);
}
}
}
void addNames(){
unsync.add("preet");
}
}
In multithreaded environment you should consider using CopyOnWriteArrayList which doesn't produce ConcurrentModificationException
The javadoc for Collections.synchronizedList(...) explains what you need to do:
void displayUnsyncList() {
synchronized (unsync) {
ListIterator<String> itr = unsync.listIterator();
while (itr.hasNext()) {
String x = itr.next();
System.out.println("Thread " +
Thread.currentThread().getName() +
" is displaying name : " + x);
}
}
In short, your code was synchronizing on the wrong object.
The iterator you are using is fail-fast iterator.Fail-fast iterator read internal data structure directly . The internal data structure should not be modified while iterating through the collection.
You should use Fail-safe iterator when one or more thread is iterating over the collection, in between, one thread changes the structure of the collection.
public static void main(String args[]) {
ArrayList<String> al = new ArrayList<String>();
List<String> sal = Collections.synchronizedList(al);
String names[] = { "amol", "Robin", "vikas", "shanu", "mahesh" };
for (String x : names) {
al.add(x);
}
Thread t1 = new Thread(new SyncArrayList(sal));
Thread t2 = new Thread(new SyncArrayList(sal));
t1.setName("T1");
t2.setName("T2");
t1.start();
t2.start();
}
}
class SyncArrayList implements Runnable {
List unsyn;
// List<String> unsync = Collections.synchronizedList(unsyn);
SyncArrayList(List<String> l) {
this.unsyn = new CopyOnWriteArrayList<String>(l);
}
#Override
public void run() {
displayUnsyncList();
addNames();
}
void displayUnsyncList() {
synchronized (this) {
Iterator<String> it = unsyn.iterator();
while (it.hasNext()) {
System.out.println("Thread " + Thread.currentThread().getName() + " is displaying name : " + it.next());
}
}
}
void addNames() {
unsyn.add("preet");
}

How do I get join() or wait() to work here? Java threads and concurrency

The code in this question was clearly too long so I've written an example you can just copy and paste that I think encompasses the conceptual problem I'm having.
Thanks to those who read all the way through the previous version!
Two files
One calls the other and passes an ArrayList.
The 2nd file alters the ArrayList and provides a getter for the first file to access the altered file.
How can I make the first file wait for the processing in the second file, before calling the getter. At the moment this code gives you a NullPointerException because the first file isn't waiting.
join() on the thread of execution doesn't seem to work, and if I use wait(), how do I notify() to the first file from the second file?
Here's the code:
public class Launcher implements Runnable {
private ArrayList al = new ArrayList();
private ArrayProcessor ap;
public Launcher(ArrayList al){
this.al = al;
ArrayProcessor ap = new ArrayProcessor(al);
}
public static void main(String[] args){
ArrayList anArray = new ArrayList();
anArray.add(new Integer(1));
anArray.add(new Integer(13));
anArray.add(new Integer(19));
Launcher l = new Launcher(anArray);
l.liftOff();
}
public void liftOff(){
Thread t = new Thread(new Launcher(al));
synchronized(t){
t.start();
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.ap = new ArrayProcessor(al);
System.out.println("the array: " + ap.getArray());
}
public void run() {
ap.doProcess(al);
}
}
and the called file:
public class ArrayProcessor extends Thread{
private ArrayList al;
public ArrayProcessor(ArrayList al){
this.al = al;
}
public void doProcess(ArrayList myAL){
this.start();
}
public void run() {
// this should increment the ArrayList elements by one
for (int i=0; i<al.size(); i++){
int num = ((Integer)al.get(i)).intValue();
al.set(i, new Integer(++num));
}
}
public ArrayList getArray(){
return al;
}
}
If you want one thread wait for another to finish you could use a CountDownLatch. Since there is a lot of code in your samples, here is a small POC:
public static void main(String[] args) throws Exception {
final CountDownLatch latch = new CountDownLatch(1);
new Thread(new Runnable() {
#Override
public void run() {
try {
System.out.println("Thread doing some work...");
Thread.sleep(10 * 1000);
System.out.println("Thread done!");
latch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}).start();
System.out.println("Main Thread waiting...");
latch.await();
System.out.println("Main Thread can continue");
}

values updated by a thread of different class not reflecting in an another class in java

I have edited my question and made it very simple.
First there are two classes on a same file
HashMapClass: which creates instance of ConccurentHashMap
and
NewThread: which updates the hashMap
public class HashMapClass {
public static volatile ConcurrentHashMap serverMap = new ConcurrentHashMap();
public static void main(String args[]) {
NewThread nt = new NewThread();
nt.start();
}
}
class NewThread extends Thread {
#Override
public void run() {
HashMapClass.serverMap.put("Ishan", new Integer(3));
System.out.println("Hash map is empty or not " + HashMapClass.serverMap.isEmpty());
try {
Thread.sleep(10000);
} catch (InterruptedException ex) {
Logger.getLogger(NewThread.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
Now here it shows that the hashMap is not empty but if i try to access it from other class New Class it shows empty
public class NewClass {
public static void main(String s[]) {
System.out.println("Hash map is empty or not " + HashMapClass.serverMap.isEmpty());
Set setMap = HashMapClass.serverMap.entrySet();
Iterator i = setMap.iterator();
for (int f = 0; i.hasNext(); ++f) {
Map.Entry me = (Map.Entry) i.next();
System.out.println("key is" + me.getKey() + "value is :" + me.getValue());
}
}
}
this class is never updated with the data.
I hope this is easy to understand now.
HashMap is not thread safe so you need to introduce some form of synchronization if you need to share a HashMap accross threads.
Alternatively, and more simply, use a ConcurrentHashMap which is thread safe.
As a side not, you would probably benefit from reading the Java tutorial on concurrency, especially the part on Memory consistency errors.
EDIT
Following your comment, see a simple example that, I think, isolates your issue - the output on my machine is:
Hash map empty in main (1st attempt)? true
Hash map empty in run? false
Hash map empty in main (2nd attempt)? false
public class Test {
public static ConcurrentMap serverMap = new ConcurrentHashMap();
public static void main(String[] args) throws InterruptedException {
NewThread nt = new NewThread();
nt.start();
System.out.println("Hash map empty in main (1st attempt)? " + serverMap.isEmpty());
Thread.sleep(200);
System.out.println("Hash map empty in main (2nd attempt)? " + serverMap.isEmpty());
}
static class NewThread extends Thread {
#Override
public void run() {
serverMap.put("Ishan", new Integer(3));
System.out.println("Hash map empty in run? " + serverMap.isEmpty());
}
}
}
2ND EDIT
You can apply the same logic from another class - just make sure you call NewThread.start and wait enough (or just call NewThread.run directly so that it is run in the same thread and you don't have to wait):
public class NewClass {
public static void main(String s[]) throws InterruptedException {
new Test.NewThread().start();
System.out.println("Hash map is empty or not (1): " + Test.serverMap.isEmpty());
Thread.sleep(100);
System.out.println("Hash map is empty or not (2): " + Test.serverMap.isEmpty());
Set setMap = Test.serverMap.entrySet();
Iterator i = setMap.iterator();
for (int f = 0; i.hasNext(); ++f) {
Map.Entry me = (Map.Entry) i.next();
System.out.println("key is" + me.getKey() + "value is :" + me.getValue());
}
}
}
HashMap needs to be handled on its synchronization part, as its lacking thread safety
ConcurrentHashMap is better at concurrency, ConcurrentHashMap will not lock the Map while one is reading , neither will it lock the entire Map when writing to it. It gonna lock the part of the Map that is being written at present.
But its important to note that ConcurrentHashMap will not throw ConcurrentModificationException, if the ConcurrentHashMap is changed during its iteration.
Edited Code:
The problem was the HashMapClass and NewClass execution, when JVM has shutdown, after HashMapClass has completed its execution, how can we run NewClass class and try to retrieve the value which is stored in the ConcurrentHashMap, which is stored on the Heap, which is all lost as soon as jvm teminates. And yes as ConcurrentHashMap is marked static the value is stored in Memory-Area of the heap
public class HashMapClass {
public static ConcurrentHashMap<String,Integer> serverMap = new ConcurrentHashMap<String,Integer>();
public static void main(String args[]) {
NewThread nt = new NewThread();
nt.start();
try {
nt.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
new NewClass().go();
}
}
class NewThread extends Thread {
#Override
public void run() {
HashMapClass.serverMap.put("Ishan", 3);
System.out.println("Hash map is empty or not " + HashMapClass.serverMap.isEmpty());
}
}
class NewClass {
public void go() {
System.out.println("Hash map is empty or not " + HashMapClass.serverMap.isEmpty());
for(Map.Entry<String,Integer> m : HashMapClass.serverMap.entrySet()){
System.out.println(m.getKey()+" "+m.getValue());
}
}
}

Exchanger appears to not exchange()

I have a pretty simple problem, in wich I try to exchange an object ( in this case an array of int) between two task : Producer and Consumer. The Producer class produces an array of int and than it tries to exchange it with the Consumer array ( which is an empty array) using an Exchanger object. But it seems that it doesn't work: when the Consumer tries to print the array, it gets nothing.
public class Producer implements Runnable{
private Exchanger<List<Integer>> exchanger;
private List<Integer> ints = new ArrayList<Integer>();
public Producer(Exchanger<List<Integer>> ex) {
this.exchanger = ex;
}
public void run() {
RandomGenerator.Integer gen = new RandomGenerator.Integer();
try{
while(!Thread.interrupted()) {
for (int i = 0;i < Test.LIST_SIZE;i++)
ints.add(gen.next());
exchanger.exchange(ints);
//for(Integer x : ints)
//System.out.print(" " + x);
//System.out.println();
}
}catch(InterruptedException e) {
System.out.println("Producer interrupted");
}
}
}
public class Consumer implements Runnable {
private Exchanger<List<Integer>> exchanger;
private List<Integer> ints = new ArrayList<Integer>();
public Consumer(Exchanger<List<Integer>> ex) {
this.exchanger = ex;
}
public void run() {
try{
while(!Thread.interrupted()) {
exchanger.exchange(ints);
System.out.println("Consumer:");
for(Integer x : ints) {
System.out.print(" " + x);
ints.remove(x);
}
System.out.println();
}
} catch(InterruptedException e) {
System.out.println("Consumer interrupted");
}
}
}
public class Test {
public static final int LIST_SIZE = 10;
public static void main(String[] args) throws InterruptedException {
ExecutorService exec = Executors.newCachedThreadPool();
Exchanger<List<Integer>> exchanger = new Exchanger<List<Integer>>();
exec.execute(new Producer(exchanger));
exec.execute(new Consumer(exchanger));
TimeUnit.MILLISECONDS.sleep(5);
exec.shutdownNow();
}
If i uncomment the lines in Producer i see that the numbers generated are still there. So why does it not exchange the object?
The exchanger does not swap the references in place, but returns the exchanged object. So you should write something like:
List<Integer> received = exchanger.exchange(ints);
System.out.println("Consumer:");
for(Integer x : received) {
System.out.print(" " + x);
...
}
BTW, I don't think exchangers are appropriate for producer/consumers...
The exchange isn't magical; the Exchanger object can't replace the object references itself. The documentation tells us that calling the function returns the object that was provided by the other thread, once the exchange point was reached, which is how we "receive" it. I haven't actually done any of this, but I assume you're meant to assign this result back; i.e. ints = exchanger.exchange(ints); in both classes.

Categories

Resources