Skip to content

Instantly share code, notes, and snippets.

@lanhuai
Created January 27, 2016 13:26
Show Gist options
  • Save lanhuai/ec61fb02d223fa907cad to your computer and use it in GitHub Desktop.
Save lanhuai/ec61fb02d223fa907cad to your computer and use it in GitHub Desktop.
volatile with trouble
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.CountDownLatch;
public class VolatileDemo {
private volatile boolean add = true;
private volatile boolean running = true;
// private volatile List<Integer> integerList = new CopyOnWriteArrayList<Integer>();
private volatile List<Integer> integerList = Collections.synchronizedList(new ArrayList<Integer>());
// private final Object lock = new Object();
private List<Integer> numberList;
public void initNumberList(int count) {
numberList = new ArrayList<Integer>(count);
for (int i = 0; i < count; i++) {
numberList.add(i);
}
}
public List<Integer> getNumberList() {
return numberList;
}
public void addNumber(Integer number) {
while (running) {
if (add) {
// synchronized (lock) {
integerList.add(number);
// }
break;
}
}
}
public List<Integer> harvest() throws InterruptedException {
add = false;
List<Integer> temp;
// synchronized (lock) {
temp = integerList;
integerList = Collections.synchronizedList(new ArrayList<Integer>());
// integerList = new CopyOnWriteArrayList<Integer>();
// temp = new ArrayList<Integer>(integerList);
// temp = Collections.synchronizedList(new ArrayList<Integer>(integerList));
// integerList.clear();
// }
// System.out.println(Thread.currentThread().getName() + " Before add = true, Snapshot List size " + temp.size() + ", new List size " + integerList.size());
/*
if (Arrays.equals(temp.toArray(), integerList.toArray())) {
System.out.println(Thread.currentThread().getName() + " duplicate ");
}
*/
add = true;
// System.out.println(Thread.currentThread().getName() + " After add = true, Snapshot List size " + temp.size() + ", new List size " + integerList.size());
return temp;
}
public static void main(String[] args) throws InterruptedException {
for (int i = 0; i < 10; i++) {
runOnce();
}
}
private static void runOnce() throws InterruptedException {
final VolatileDemo volatileDemo = new VolatileDemo();
int threadCount = 1000;
volatileDemo.initNumberList(threadCount);
final CountDownLatch producerLatch = new CountDownLatch(threadCount);
final CountDownLatch consumerLatch = new CountDownLatch(threadCount);
Thread[] producerThreads = new Thread[threadCount];
for (int i = 0; i < producerThreads.length; i++) {
final int number = i;
producerThreads[i] = new Thread(new Runnable() {
@Override
public void run() {
volatileDemo.addNumber(number);
producerLatch.countDown();
}
}, "producerThread-" + i);
}
final List<Integer> elementCountList = new CopyOnWriteArrayList<Integer>();
final Set<Integer> harvestElementList = new CopyOnWriteArraySet<Integer>();
Thread[] consumerThreads = new Thread[threadCount];
for (int i = 0; i < consumerThreads.length; i++) {
consumerThreads[i] = new Thread(new Runnable() {
@Override
public void run() {
try {
List<Integer> harvest = volatileDemo.harvest();
int numberCount = harvest.size();
if (numberCount != 0) {
elementCountList.add(numberCount);
harvestElementList.addAll(harvest);
}
consumerLatch.countDown();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}, "consumerThread-" + i);
}
for (int i = 0; i < threadCount; i++) {
producerThreads[i].start();
consumerThreads[i].start();
}
volatileDemo.running = false;
producerLatch.await();
consumerLatch.await();
System.out.println(elementCountList.size() + " harvest have elements count > 0");
int totalElementCount = 0;
for (Integer count : elementCountList) {
totalElementCount += count;
}
System.out.println("Harvest " + totalElementCount + " elements with duplicate, infact is " + harvestElementList.size());
List<Integer> numberList = volatileDemo.getNumberList();
numberList.removeAll(harvestElementList);
System.out.println("Lost " + numberList.size() + " elements !!!");
System.out.print("[");
for (int i = 0; i < numberList.size(); i++) {
Integer integer = numberList.get(i);
System.out.print(integer);
if (i != numberList.size() - 1) {
System.out.print(",");
}
}
System.out.println("]");
System.out.println();
System.out.println();
System.out.println();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment