Java Concurrency In Practice by Brian Goetz provides an example of a efficient scalable cache for concurrent use. Here is the code for the class:
public class Memoizer<A, V> implements Computable<A, V> {
private final ConcurrentMap<A, Future<V>> cache
= new ConcurrentHashMap<A, Future<V>>();
private final Computable<A, V> c;
public Memoizer(Computable<A, V> c) { this.c = c; }
public V compute(final A arg) throws InterruptedException {
while (true) {
Future<V> f = cache.get(arg);
if (f == null) {
Callable<V> eval = new Callable<V>() {
public V call() throws InterruptedException {
return c.compute(arg);
}
};
FutureTask<V> ft = new FutureTask<V>(eval);
f = cache.putIfAbsent(arg, ft);
if (f == null) { f = ft; ft.run(); }
}
try {
return f.get();
} catch (CancellationException e) {
cache.remove(arg, f);
} catch (ExecutionException e) {
throw launderThrowable(e.getCause());
}
}
} }
Probably a stupid question but coudl anyone show me the concurrent usage of this class?
Like in a main?
Cheers,
Agata
Here is an example which calculates factorials:
public static void main(String[] args) throws Exception {
//create a memoizer that performs factorials
final Memoizer<Integer, Integer> memo = new Memoizer<Integer, Integer> (new Computable<Integer, Integer>() {
#Override
public Integer compute(Integer a) {
int result = 1 ;
for(int i = 1 ; i < a ; i++){
result = result*i;
}
return result;
}
});
//now call the memoizer
System.out.println(memo.compute(10));
//call it with 10 threads concurrently
ExecutorService exec = Executors.newFixedThreadPool(10);
ExecutorCompletionService<Integer> compService = new ExecutorCompletionService<Integer>(exec);
for(int i = 0 ; i < 15 ; i++){
compService.submit(new Callable<Integer>(){
#Override
public Integer call() throws Exception {
return memo.compute(5);
}
});
}
exec.shutdown();
for(int i = 0 ; i < 15 ; i++){
System.out.println(compService.take().get());
}
}
So if two threads try to compute the same factorial at exactly the same time, only one of them will actually perform the computation, because putIfAbsent is threadsafe. The second thread will simply get the future which was put in the map by the first thread and wait for it to finish.
I could imagine something like this:
class PrimeDetector implements Computable<BigInteger, Boolean> {
public Boolean compute(BigInteger number) {
// detect whether the number is prime and return true if it is
}
}
Memoizer<BigInteger, Boolean> primeMemoizer =
new Memoizer<BigInteger, BigInteger[]>(new PrimeDetector());
boolean isPrime = primeMemoizer.compute(
new BigInteger("5625945193217348954671586615478165774647538956473535"));
...
Related
I want to call a method in java but synchronized and first-in-first-out.
Currently I call the method like so:
synchronized (synchronizeObject) {
executeMethode(object1, object2);
}
I found out, that synchronized does not actually care in what order something is added.
Is there an easy way to force FIFO?
I do not think ArrayBlockingQueue is applicable here, At least not in a way I see it, but I may be wrong
Here is a snippet:
public class AppTest {
#Test
void test() throws InterruptedException {
ExecutorService pool = Executors.newFixedThreadPool(8);
FairLockedMethod<Integer> method = new FairLockedMethod<>() {
#Override
protected void lockedMethod(Integer i) {
System.out.println(i);
try {
Thread.currentThread().wait(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
for (int i = 0; i < 16; i++) {
int n = i;
pool.submit(() ->method.run(n));
}
pool.shutdown();
pool.awaitTermination(10, TimeUnit.SECONDS);
}
public static abstract class FairLockedMethod<T> {
protected abstract void lockedMethod(T value);
private final ReentrantLock lock = new ReentrantLock(true);
private final Condition condition = lock.newCondition();
private final Queue<Thread> queue = new LinkedBlockingDeque<>();
public void run(T value) {
queue.offer(Thread.currentThread());
lock.lock();
try {
while (queue.peek() != Thread.currentThread()) {
condition.await();
}
queue.poll();
condition.signalAll();
lockedMethod(value);
} catch (InterruptedException e) {
throw new RuntimeException(e);
} finally {
lock.unlock();
}
}
}
}
It is not most efficient implementation, but simplest I can come with.
I am kinda new to threads. How can I prove, by writing code in a separate class, that MyClass class isn't thread safe? I've been searching but I can't really find an example to aid me.
public class MyClass {
private static int value = 0;
public static void set(int setVal) {
value = setVal;
}
public static int get() {
return value;
}
public static void decrement() {
int temp = value;
value = --temp;
}
}
public static void main(String[] args) {
int nt = 10;
int c = 20000;
MyClass.set(c);
Thread[] threads = new Thread[nt];
for (int t = 0; t < nt; t++) {
Thread thread = new Thread(() -> {
for (int i = 0; i < c; i += nt) {
MyClass.decrement();
}
});
thread.start();
threads[t] = thread;
}
try {
for (Thread thread : threads) {
thread.join();
}
} catch (Throwable tr) {
tr.printStackTrace();
}
System.out.println(MyClass.get());
}
Try this. If you add synchronized to the decrement method of MyClass it will print out 0 (thread safe), but if you don't synchronize decrement than it will print out a wrong number.
This proves that MyClass (its decrement method) is not thread prove, since if it was it would print out 0.
Also, if you can't use lambdas than replace the first for loop with the following:
for (int t = 0; t < nt; t++) {
Thread thread = new Thread(() -> {
for (int i = 0; i < c; i += nt) {
MyClass.decrement();
}
});
thread.start();
threads[t] = thread;
}
Hope I could help!
public class ThreadTest {
private final ListeningExecutorService executor;
public ThreadTest() {
this.executor = MoreExecutors.listeningDecorator(Executors.newCachedThreadPool());
}
public void processAsync() {
int i=0;
do {
final Future<Integer> future = processThread(i));
futures.add(future);
i++;
} while (i<10);
int count = 0;
for (Future<Integer> f : futures) {
try {
count+=f.get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException("Error occurred", e);
}
}
}
private Integer updateCount(Integer i) {
Integer a = Math(i,2);
a = a + 20;
Integer b = a + 40;
return b;
}
public ListenableFuture<Integer> processThread(Integer i) {
return this.executor.submit(()->{
return updateCount(i);
});
}
In this small snippet of code, would I need to synchronize anything in the updateCount() method if I called the processAsync() method of the class? Would multiple threads invoking updateCount() result in the temporary variables being created(i, a , b) to be out of synch and return garbage values?
The class below updates a map in particluar interval of time.
public class CheckerThread extends Thread {
private volatile HashMap<String, Integer> map = new HashMap<>();
#Override
public void run() {
while (true) {
updateMap();
try {
Thread.sleep(1000);
}
catch (InterruptedException e) {
// Do something
}
}
}
private void updateMap() {
HashMap<String, Integer> localMap = new HashMap<>();
int count = 0;
while (count < 10) {
localMap.put(count + "a", count);
count++;
}
this.map = localMap;
}
public Map<String, Integer> getMap() {
return this.map;
}
}
The Class below calls the method getMap() to get the Map . I need to ensure the list is fully updated before returning the map in the class "CheckerThread". The method should wait till map is updated.
public class GetterThread extends Thread {
private final CheckerThread checkerThread;
public GetterThread(final CheckerThread checkerThread) {
this.checkerThread = checkerThread;
}
#Override
public void run() {
System.err.println(this.checkerThread.getMap());
}
}
Another class Main creates threads.
public class MainThread extends Thread {
public static void main(final String[] args) throws InterruptedException {
int i = 0;
GetterThread[] getterThreads = new GetterThread[5];
CheckerThread checkerThread = new CheckerThread();
checkerThread.start();
while (i < 5) {
getterThreads[i] = new GetterThread(checkerThread);
getterThreads[i].start();
Thread.sleep(1000);
i++;
}
}
}
}
The idea of a threading is ok for that but not enough (most of them because threads don't return anything after they do the job...) if you want to still work with threads then you will end in a wait/join/notify approach...
you can instead of a thread --> runnable use a task --> callable,
Callables are threads on steroids, you can execute them in a ExecutorService and wait until the job is done getting even a result that let you know if everything went ok or not!!
take this as an example and consult the doc for more information:
ExecutorService
FutureTask
Callabel
public class _Foo {
public static void main(String... args) throws InterruptedException, ExecutionException {
ExecutorService exService = Executors.newSingleThreadExecutor();
FutureTask<Boolean> futureTask = new FutureTask<>(new MapCleaner());
exService.execute(futureTask);
System.out.println("Was everything ok??: " + futureTask.get());
}
}
class MapCleaner implements Callable<Boolean> {
#Override
public Boolean call() {
try {
Thread.sleep(3000);
} catch (InterruptedException ex) {
System.out.println(ex);
}
return System.currentTimeMillis() % 2 == 0;
}
}
Have you looked at Futures? Future.get() waits for task to get completed. Could this be what you need?
public class MyCallable implements Callable<Map<String, Integer>> {
private volatile HashMap<String, Integer> map = new HashMap<>();
private boolean wait = true;
public void call() {
while (wait) {
updateMap();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
}
return map;
}
private void updateMap() {
HashMap<String, Integer> localMap = new HashMap<>();
int count = 0;
while (count < 10) {
localMap.put(count + "a", count);
}
this.map = localMap;
wait = false;
}
}
and just call the future
ExecutorService executor = Executors.newSingleThreadExecutor();
Future<Map<String, Integer>> future = executor.submit(new MyCallable());
// Future.get() waits for task to get completed
Map<String, Integer> myMap = fut.get();
Based on your example, I think you should be using a BlockingQueue. Put elements into the queue in your "checker" thread, and read them with a blocking wait in the "getter" thread. This is easy and pretty clean, not too many changes are needed.
A queue will solve not only synchronization problems for you but also timing problems. No matter which order your threads run, your getter thread always waits until data is available, then returns. It's pretty much bomb proof.
BTW you have a bug in your checker thread. You put ten elements into the map, but you never increment count, so that loop never exits (it puts an infinite number of elements into the map, you'll get an out of memory error eventually).
Also, never ever catch and ignore InterruptedException. You almost always want to exit your thread if you get interrupted. C.f. Brian Goetz's book Java Concurrency in Practice for more.
public class SimpleThreading
{
public static void main(String[] args) throws InterruptedException {
MainThread.main(args);
}
}
class MainThread extends Thread
{
public static void main( final String[] args )
throws InterruptedException
{
int i = 0;
GetterThread[] getterThreads = new GetterThread[ 5 ];
CheckerThread checkerThread = new CheckerThread();
checkerThread.start();
while( i < 5 ) {
getterThreads[i] = new GetterThread( checkerThread );
getterThreads[i].start();
Thread.sleep( 1000 );
i++;
}
}
}
class GetterThread extends Thread
{
private final CheckerThread checkerThread;
public GetterThread( final CheckerThread checkerThread )
{
this.checkerThread = checkerThread;
}
#Override
public void run()
{
try {
System.out.println("waiting..." + checkerThread.getQueue() );
System.err.println( this.checkerThread.getQueue().take() );
} catch( InterruptedException ex ) {
// exit on interrupt
}
}
}
class CheckerThread extends Thread
{
private HashMap<String, Integer> map;
private final BlockingQueue<Map<String,Integer>> queue =
new LinkedBlockingQueue<>();
#Override
public void run()
{
while( true )
try {
updateMap();
queue.put( map );
System.out.println( "Added " + map );
Thread.sleep( 1000 );
} catch( InterruptedException e ) {
return; // exit on interrupt
}
}
private void updateMap()
{
HashMap<String, Integer> localMap = new HashMap<>();
int count = 0;
while( count < 10 )
localMap.put( count + "a", count++ );
this.map = localMap;
}
public BlockingQueue<Map<String, Integer>> getQueue()
{
return queue;
}
}
I have a following code as below:
class Example {
private volatile int testValue = 0;
public int getTestValue() {
return testValue;
}
public void setTestValue(int testValue) {
this.testValue = testValue;
}
public void increment() {
this.testValue += 1;
}
}
class PrintThread extends Thread {
private Example example;
private int x = 0;
public PrintThread(Example example) {
this.example = example;
x = example.getTestValue();
}
public void run() {
while(true) {
if(x != example.getTestValue()) { // block 1
System.out.println("printThread: " + example.getTestValue());
x = example.getTestValue();
}
}
}
}
class IncrementorThread extends Thread {
private Example example;
public IncrementorThread(Example example) {
this.example = example;
}
public void run() {
while(true) {
example.increment();
System.out.println("incrementorThread: " + example.getTestValue());
try {
Thread.sleep(800);
} catch(Exception ex) {
}
}
}
}
public class VolatileExample {
public static void main(String args[]) {
Example ex = new Example();
new IncrementorThread(ex).start();
new PrintThread(ex).start();
}
}
When I remove volatile keyword in Example class then I never see the output of PrintThread. In PrintThread when I print out the testValue of example, value of example object still updated but the code in 'block 1' never be executed. Both thread still access the same object, can anyone explain me more detail about this? About the volatile keyword affected in this case
You should use atomic integers insteed of volatile fields. To get the idea why that is important try running code below. Here you have 3 types of variables, normal int, volatile int and AtomicInteger. Only AtomicInteger assure the thread safety of value. After running this simple code, you will see why.
public class Test {
private int threadCount = 10;
private int nonVolatileCount = 0;
private volatile int volatileCount = 0;
private AtomicInteger atomicCount = new AtomicInteger(0);
private CountDownLatch startLatch = new CountDownLatch(threadCount);
private CountDownLatch endLatch = new CountDownLatch(threadCount);
private class Task implements Runnable {
public void run() {
startLatch.countDown();
try {
startLatch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 1000000; i++) {
nonVolatileCount++;
volatileCount++;
atomicCount.incrementAndGet();
}
endLatch.countDown();
};
}
public static void main(String[] args) throws InterruptedException {
new Test().go();
}
public void go() throws InterruptedException {
for (int i = 0; i < threadCount; i++) {
new Thread(new Task()).start();
}
endLatch.await();
System.out.println("non volatile counter: " + nonVolatileCount);
System.out.println(" volatile counter: " + volatileCount);
System.out.println(" atomic counter: " + atomicCount.get());
}
}