Main thread creates child thread. Parent needs some work from child, but not all of it, so parent must wait until child finish that work (child will keep doing some other work).
I would like to achieve it with monitors so I coded the following:
public class WaitChildThreadMonitor {
public static final int TOTAL_COUNT_AMOUNT = 1_000;
static int count = 0;
class Child implements Runnable {
#Override
public void run() {
work();
}
public synchronized void work() {
letParentWaitForThis();
for (int i = 0; i < TOTAL_COUNT_AMOUNT; i++)
++WaitChildThreadMonitor.count;
this.notifyAll();
// More child work that parent doesn't need right now
// ...
for (int i = 0; i < TOTAL_COUNT_AMOUNT; i++)
++WaitChildThreadMonitor.count;
}
private void letParentWaitForThis() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
}
public synchronized void waitForWork() throws InterruptedException {
this.wait();
}
}
void main() throws InterruptedException {
Child child = new Child();
Thread childThread = new Thread(child);
// If the next two methods doesn't execute atomically,
// parent execution gets blocked forever
childThread.start();
child.waitForWork();
System.out.printf("Count value is %d\n", WaitChildThreadMonitor.count);
childThread.join();
}
public static void main(String[] args) throws InterruptedException {
(new WaitChildThreadMonitor()).main();
}
}
The problem is that if child executes "this.notifyAll()" after he finished his main work before parent executes "this.wait()" in "child.waitForWork()", parent won't get notified and will get blocked forever.
I tried to solve it forcing a context switch before child start his work using Thread.sleep() method. It doesn't seem to work as expected.
With sleep and without sleep, sometimes parent gets blocked and program never ends, sometimes it ends properly (I guess because parent waited before child notified).
How can I fix this?
Thanks in advance!
You must not call wait if the thing you want to wait for has already happened. That's the reason the method that calls wait is synchronized -- so you can check the shared state that represents the thing you're waiting for.
So this is a standard producer-consumer problem. A long time ago, I wrote an implementation using only synchronized and wait-notify. I don't see what your code produces; this code just uses int as the thing produced. Change the type of the array inside Storage for some other class type.
package quicktest;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
/**
*
* #author Brenden Towey
*/
public class ProducerConsumer {
public static void main(String[] args) throws InterruptedException {
Storage circularBuffer = new Storage();
Counter producer1 = new Counter( circularBuffer, 1000 );
Counter producer2 = new Counter( circularBuffer, 2000 );
Counter producer3 = new Counter( circularBuffer, 3000 );
Counter producer4 = new Counter( circularBuffer, 4000 );
ExecutorService exe = Executors.newCachedThreadPool();
exe.execute( producer1 );
exe.execute( producer2 );
exe.execute( producer3 );
exe.execute( producer4 );
Printer consumer = new Printer( circularBuffer );
exe.execute( consumer );
Thread.sleep( 100 );// wait a bit
exe.shutdownNow();
exe.awaitTermination( 10, TimeUnit.SECONDS );
}
}
// Producer
class Counter implements Runnable {
private final Storage output;
private final int startingValue;
public Counter(Storage output, int startingValue) {
this.output = output;
this.startingValue = startingValue;
}
#Override
public void run() {
try {
for( int i = startingValue; ; i++ )
output.put(i);
} catch (InterruptedException ex) {
// exit...
}
}
}
class Storage {
private final int[] buffer = new int[20];
private int head;
private int count;
public synchronized void put( int i ) throws InterruptedException {
while( count == buffer.length ) wait();// full
buffer[head++] = i;
head %= buffer.length;
count++;
notifyAll();
}
public synchronized int get() throws InterruptedException {
while( count == 0 ) wait(); // empty
int tail = (head - count) % buffer.length;
tail = (tail < 0) ? tail + buffer.length : tail;
int retval = buffer[tail];
count--;
notifyAll();
return retval;
}
}
// Consumer
class Printer implements Runnable {
private final Storage input;
public Printer(Storage input) {
this.input = input;
}
#Override
public void run() {
try {
for( ;; )
System.out.println( input.get() );
} catch (InterruptedException ex) {
// exit...
}
}
}
Related
Trying to make a simple multi-threaded programme where it prints Factorial series where each number is printed by different Thread and at the end I am giving a report of which number printed by which thread.I have got the desired output but somehow my program is not terminating.
Constraint: I am not allowed to use Concurrent Package
import java.util.ArrayList;
import java.util.Scanner;
class Report {
private long factorial;
private String threadName;
private int activeThreads;
public Report(long factorial, String threadName, int activeThreads) {
this.factorial = factorial;
this.threadName = threadName;
this.activeThreads = activeThreads;
}
public long getFactorial() {
return factorial;
}
public String getThreadName() {
return threadName;
}
public int getActiveThreads() {
return activeThreads;
}
public void setActiveThreads(int activeThreads) {
this.activeThreads = activeThreads;
}
}
public class Factorial implements Runnable {
public static ArrayList<Report> report = new ArrayList<Report>();
private static int count;
public static void main(String[] args) throws InterruptedException {
Scanner in = new Scanner(System.in);
System.out.print("N: ");
int n = in.nextInt();
count = n;
Factorial f = new Factorial();
f.series(n);
Thread.sleep(1000);
// Series
for(Report r : report) {
if(r.getFactorial() == 1) {
System.out.print(r.getFactorial());
}
else {
System.out.print(r.getFactorial() + "*");
}
}
System.out.println();
// Report
for(Report r : report) {
System.out.println(r.getFactorial() + " printed by " + r.getThreadName() + " " + r.getActiveThreads());
}
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
System.out.println("In Main");
in.close();
}
public void series(int n) throws InterruptedException {
for(int i=0;i<n;i++) {
Thread t = new Thread(new Factorial());
t.start();
}
}
public synchronized void generate() {
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
report.add(new Report(count--, Thread.currentThread().getName(), threadGroup.activeCount()));
notifyAll();
System.out.println("In generate" + threadGroup.activeCount());
}
#Override
public void run() {
generate();
synchronized (this) {
try {
wait();
}
catch(Exception e) {
e.printStackTrace();
}
}
ThreadGroup threadGroup = Thread.currentThread().getThreadGroup();
System.out.println("In Run" + threadGroup.activeCount());
}
public static int getCount() {
return count;
}
public static void setCount(int count) {
Factorial.count = count;
}
}
Although I know that we can kill the threads using .stop() but I think it's not recommended.
To make synchronization effective (synchronized, wait, notify), you have to use the same instance.
In series, you create a new Factorial instance on each loop, making every thread to wait indefinitely.
public void series(int n) throws InterruptedException {
for(int i=0;i<n;i++) {
// Thread t = new Thread(new Factorial()); // creates an new instance
Thread t = new Thread(this);
t.start();
}
}
In the run method, you first call notifyAll() (through generate), and then wait.
The last created thread will wait after all the others are done.
One way or another, this last thread has to be notified.
It could be right after the sleep call, with:
synchronized(f) {
f.notify();
}
or maybe with a dedicated synchronized method.
I have to create a hedge simulator. There is eg. 10 segments of it and each of them should have its own dedicated Thread simulating grow of the segment (each time we're about to calculate whether segment growed up, we should perform random test).
In addition there should be one additional, gardener Thread.
Gardener should cut segment of hence, when its size reaches 10 (then he cuts its size back to initial level of 1 and adds notifies it in his notes).
My attempt to make it working was like this:
public class Segment implements Runnable {
private int currentSize;
#Override
public void run() {
if(Math.random() < 0.3)
incrementSize();
}
private synchronized void incrementSize() {
currentSize++;
}
public synchronized int getCurrentSize() {
return currentSize;
}
public synchronized void setCurrentSize(int newSize) {
currentSize = newSize;
}
}
public class Gardener implements Runnable {
private int[] segmentsCutAmount = new int[10]; //Gardener notes
private Collection<Segment> segments;
public Gardener(Collection<Segment> segmentsToLookAfter) {
segments = segmentsToLookAfter;
}
#Override
public void run() {
while(true) {
//Have no idea how to deal with 10 different segments here
}
}
}
public class Main {
private Collection<Segment> segments = new ArrayList<>():
public void main(String[] args) {
Main program = new Main();
for(int i = 0; i < 10; i++)
program.addSegment();
Thread gardenerThread = new Thread(new Gardener(program.segments));
}
private void addSegment(Collection<Segment> segments) {
Segment segment = new Segment();
Thread segmentThread = new Thread(segment);
segmentThread.start();
segments.add(segment);
}
}
I am not sure what am I supposed to do, when segment reaches max height.
If there was 10 gardeners, every of them could observe one segment, but, unfortunelly, gardener is a lonely shooter - he has no family and his friends are very busy and are not willing to help him. And are you willing to help me? :D
I generally know basics of synchronization - synchronized methods/blocks, Locks, wait and notify methods, but this time I have totally no idea what to do :(
Its like horrible deadlock! Of course I am not expecting to be spoonfeeded. Any kind of hint would be very helpful as well. Thank you in advance and have a wonderful day!
About that queue. You can use the ExecutorService for that.
Letting the Hedge grow
So let's you have a hedge that can grow and be cut.
class Hedge {
private AtomicInteger height = new AtomicInteger(1);
public int grow() {
return height.incrementAndGet();
}
public int cut() {
return height.decrementAndGet();
}
}
And then you have an environment that will let the hedge grow. This will simulate the hedge sections; each environment is responsible for one of the sections only. It will also notify a Consumer<Integer> when the hedge size has gone.
class SectionGrower implements Runnable {
public static final Random RANDOM = new Random();
private final Hedge hedge;
private final Consumer<Integer> hedgeSizeListener;
public SectionGrower (Hedge h, Consumer<Integer> hl) {
hedge = h;
hedgeSizeListener = hl
}
public void run() {
while (true) { // grow forever
try {
// growing the hedge takes up to 20 seconds
Thread.sleep(RANDOM.nextInt(20)*1000);
int sectionHeight = hedge.grow();
hedgeSizeListener.accept(sectionHeight);
} catch (Exception e) {} // do something here
}
}
}
So at this point, you can do this.
ExecutorService growingExecutor = Executors.newFixedThreadPool(10);
Consumer<Integer> printer = i -> System.out.printf("hedge section has grown to %d\n", i.intValue());
for (int i = 0; i < 10; i++) {
Hedge section = new Hedge();
Environment grower = new SectionGrower(section, printer);
growingExecutor.submit(grower::run);
}
This will grow 10 hedge sections and print the current height for each as they grow.
Adding the Gardener
So now you need a Gardener that can cut the hedge.
class Gardener {
public static final Random RANDOM = new Random();
public void cutHedge(Hedge h) {
try {
// cutting the hedge takes up to 10 seconds
Thread.sleep(RANDOM.nextInt(10)*1000);
h.cut();
} catch (Exception e) {} // do something here
}
}
Now you need some construct to give him work; this is where the BlockingQueue comes in. We've already made sure the Environment can notify a Consumer<Integer> after a section has grown, so that's what we can use.
ExecutorService growingExecutor = Executors.newFixedThreadPool(10);
// so this is the queue
ExecutorService gardenerExecutor = Executors.newSingleThreadPool();
Gardener gardener = new Gardener();
for (int i = 0; i < 10; i++) {
Hedge section = new Hedge();
Consumer<Integer> cutSectionIfNeeded = i -> {
if (i > 8) { // size exceeded?
// have the gardener cut the section, ie adding item to queue
gardenerExecutor.submit(() -> gardener.cutHedge(section));
}
};
SectionGrower grower = new SectionGrower(section, cutSectionIfNeeded);
growingExecutor.submit(grower::run);
}
So I haven't actually tried this but it should work with some minor adjustments.
Note that I use the AtomicInteger in the hedge because it might grow and get cut "at the same time", because that happens in different threads.
The in following code Gardner waits for Segment to get to an arbitrary value of 9.
When Segment gets to 9, it notifies Gardner, and waits for Gardner to finish trimming:
import java.util.ArrayList;
import java.util.Collection;
public class Gardening {
public static void main(String[] args) {
Collection<Segment> segments = new ArrayList<>();
for(int i = 0; i < 2; i++) {
addSegment(segments);
}
Thread gardenerThread = new Thread(new Gardener(segments));
gardenerThread.start();
}
private static void addSegment(Collection<Segment> segments) {
Segment segment = new Segment();
Thread segmentThread = new Thread(segment);
segmentThread.start();
segments.add(segment);
}
}
class Gardener implements Runnable {
private Collection<Segment> segments;
private boolean isStop = false; //add stop flag
public Gardener(Collection<Segment> segmentsToLookAfter) {
segments = segmentsToLookAfter;
}
#Override
public void run() {
for (Segment segment : segments) {
follow(segment);
}
}
private void follow(Segment segment) {
new Thread(() -> {
Thread t = new Thread(segment);
t.start();
synchronized (segment) {
while(! isStop) {
try {
segment.wait(); //wait for segment
} catch (InterruptedException ex) { ex.printStackTrace();}
System.out.println("Trimming Segment " + segment.getId()+" size: "
+ segment.getCurrentSize() ); //add size to notes
segment.setCurrentSize(0); //trim size
segment.notify(); //notify so segment continues
}
}
}).start();
}
}
class Segment implements Runnable {
private int currentSize;
private boolean isStop = false; //add stop flag
private static int segmentIdCounter = 0;
private int segmentId = segmentIdCounter++; //add an id to identify thread
#Override
public void run() {
synchronized (this) {
while ( ! isStop ) {
if(Math.random() < 0.0000001) {
incrementSize();
}
if(getCurrentSize() >= 9) {
notify(); //notify so trimming starts
try {
wait(); //wait for gardener to finish
} catch (InterruptedException ex) {
ex.printStackTrace();
}
}
}
}
}
private synchronized void incrementSize() {
currentSize++;
System.out.println("Segment " + getId()+" size: "
+ getCurrentSize() );
}
public synchronized int getCurrentSize() { return currentSize; }
public synchronized void setCurrentSize(int newSize) {
currentSize = newSize;
}
public int getId() { return segmentId; }
}
The mutual waiting mechanizem can be implemented also with CountDownLatch.
Note that my experience with threads is limited. I hope other users comment and suggest improvements.
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;
}
}
Does anyone know if there is any latch implementation that does the following:
has a method to decrement the latch value, or wait if the value is zero
has a method for waiting for the latch value to be zero
has a method for adding a number to the latch's value
You could also use a Phaser (java.util.concurrent.Phaser)
final Phaser phaser = new Phaser(1); // register self
while (/* some condition */) {
phaser.register(); // Equivalent to countUp
// do some work asynchronously, invoking
// phaser.arriveAndDeregister() (equiv to countDown) in a finally block
}
phaser.arriveAndAwaitAdvance(); // await any async tasks to complete
java.util.concurrent.Semaphore seems to fit the bill.
acquire() or acquire(n)
also acquire() (not sure I understand what the difference is here) (*)
release() or release(n)
(*) Okay, there is no built-in method to wait until the semaphore becomes unavailable. I suppose you'd write your own wrapper for acquire that does a tryAcquire first and if that fails triggers your "busy event" (and continues using the normal acquire). Everyone would need to call your wrapper. Maybe subclass Semaphore?
Instead of starting back from AQS, you could use a simple implementation like below. It is somewhat naive (it is synchronized vs. AQS lock-free algorithms) but unless you expect to use it in a contented scenario it could be good enough.
public class CountUpAndDownLatch {
private CountDownLatch latch;
private final Object lock = new Object();
public CountUpAndDownLatch(int count) {
this.latch = new CountDownLatch(count);
}
public void countDownOrWaitIfZero() throws InterruptedException {
synchronized(lock) {
while(latch.getCount() == 0) {
lock.wait();
}
latch.countDown();
lock.notifyAll();
}
}
public void waitUntilZero() throws InterruptedException {
synchronized(lock) {
while(latch.getCount() != 0) {
lock.wait();
}
}
}
public void countUp() { //should probably check for Integer.MAX_VALUE
synchronized(lock) {
latch = new CountDownLatch((int) latch.getCount() + 1);
lock.notifyAll();
}
}
public int getCount() {
synchronized(lock) {
return (int) latch.getCount();
}
}
}
Note: I have not tested it in depth but it seems to behave as expected:
public static void main(String[] args) throws InterruptedException {
final CountUpAndDownLatch latch = new CountUpAndDownLatch(1);
Runnable up = new Runnable() {
#Override
public void run() {
try {
System.out.println("IN UP " + latch.getCount());
latch.countUp();
System.out.println("UP " + latch.getCount());
} catch (InterruptedException ex) {
}
}
};
Runnable downOrWait = new Runnable() {
#Override
public void run() {
try {
System.out.println("IN DOWN " + latch.getCount());
latch.countDownOrWaitIfZero();
System.out.println("DOWN " + latch.getCount());
} catch (InterruptedException ex) {
}
}
};
Runnable waitFor0 = new Runnable() {
#Override
public void run() {
try {
System.out.println("WAIT FOR ZERO " + latch.getCount());
latch.waitUntilZero();
System.out.println("ZERO " + latch.getCount());
} catch (InterruptedException ex) {
}
}
};
new Thread(waitFor0).start();
up.run();
downOrWait.run();
Thread.sleep(100);
downOrWait.run();
new Thread(up).start();
downOrWait.run();
}
Output:
IN UP 1
UP 2
WAIT FOR ZERO 1
IN DOWN 2
DOWN 1
IN DOWN 1
ZERO 0
DOWN 0
IN DOWN 0
IN UP 0
DOWN 0
UP 0
For those needing an AQS based solution, here's one that worked for me:
public class CountLatch {
private class Sync extends AbstractQueuedSynchronizer {
private static final long serialVersionUID = 1L;
public Sync() {
}
#Override
protected int tryAcquireShared(int arg) {
return count.get() == releaseValue ? 1 : -1;
}
#Override
protected boolean tryReleaseShared(int arg) {
return true;
}
}
private final Sync sync;
private final AtomicLong count;
private volatile long releaseValue;
public CountLatch(final long initial, final long releaseValue) {
this.releaseValue = releaseValue;
this.count = new AtomicLong(initial);
this.sync = new Sync();
}
public void await() throws InterruptedException {
sync.acquireSharedInterruptibly(1);
}
public long countUp() {
final long current = count.incrementAndGet();
if (current == releaseValue) {
sync.releaseShared(0);
}
return current;
}
public long countDown() {
final long current = count.decrementAndGet();
if (current == releaseValue) {
sync.releaseShared(0);
}
return current;
}
public long getCount() {
return count.get();
}
}
You initialize the synchronizer with an initial and target value. Once the target value has been reached (by counting up and / or down), the waiting threads will be released.
I needed one and built it using the same strategy as CountDownLatch which uses AQS (non-blocking), this class is also very similar (If not exact) to one created for Apache Camel, I think it is also lighter than JDK Phaser, this will act just like CountDownLact from JDK, it won't let you count down below zero and will allow you count down and up:
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.AbstractQueuedSynchronizer;
public class CountingLatch
{
/**
* Synchronization control for CountingLatch.
* Uses AQS state to represent count.
*/
private static final class Sync extends AbstractQueuedSynchronizer
{
private Sync()
{
}
private Sync(final int initialState)
{
setState(initialState);
}
int getCount()
{
return getState();
}
protected int tryAcquireShared(final int acquires)
{
return getState()==0 ? 1 : -1;
}
protected boolean tryReleaseShared(final int delta)
{
// Decrement count; signal when transition to zero
for(; ; ){
final int c=getState();
final int nextc=c+delta;
if(nextc<0){
return false;
}
if(compareAndSetState(c,nextc)){
return nextc==0;
}
}
}
}
private final Sync sync;
public CountingLatch()
{
sync=new Sync();
}
public CountingLatch(final int initialCount)
{
sync=new Sync(initialCount);
}
public void increment()
{
sync.releaseShared(1);
}
public int getCount()
{
return sync.getCount();
}
public void decrement()
{
sync.releaseShared(-1);
}
public void await() throws InterruptedException
{
sync.acquireSharedInterruptibly(1);
}
public boolean await(final long timeout) throws InterruptedException
{
return sync.tryAcquireSharedNanos(1,TimeUnit.MILLISECONDS.toNanos(timeout));
}
}
This is a variation on CounterLatch, available from the Apache site.
Their version, for reasons best known to themselves, blocks the caller thread while the variable (AtomicInteger) is at a given value.
But it is the height of easiness to tweak this code so that you can choose either just what the Apache version does, or... to say "wait here until the counter reaches a certain value". Arguably the latter is going to have more applicability. In my particular case I rustled this up because I wanted to check that all "chunks" had been published in SwingWorker.process()... but I have since found other uses for it.
Here it is written in Jython, officially the best language in the world (TM). I am going to rustle up a Java version in due course.
class CounterLatch():
def __init__( self, initial = 0, wait_value = 0, lift_on_reached = True ):
self.count = java.util.concurrent.atomic.AtomicLong( initial )
self.signal = java.util.concurrent.atomic.AtomicLong( wait_value )
class Sync( java.util.concurrent.locks.AbstractQueuedSynchronizer ):
def tryAcquireShared( sync_self, arg ):
if lift_on_reached:
return -1 if (( not self.released.get() ) and self.count.get() != self.signal.get() ) else 1
else:
return -1 if (( not self.released.get() ) and self.count.get() == self.signal.get() ) else 1
def tryReleaseShared( self, args ):
return True
self.sync = Sync()
self.released = java.util.concurrent.atomic.AtomicBoolean() # initialised at False
def await( self, *args ):
if args:
assert len( args ) == 2
assert type( args[ 0 ] ) is int
timeout = args[ 0 ]
assert type( args[ 1 ] ) is java.util.concurrent.TimeUnit
unit = args[ 1 ]
return self.sync.tryAcquireSharedNanos(1, unit.toNanos(timeout))
else:
self.sync.acquireSharedInterruptibly( 1 )
def count_relative( self, n ):
previous = self.count.addAndGet( n )
if previous == self.signal.get():
self.sync.releaseShared( 0 )
return previous
NB the Apache version uses the keyword volatile for signal and released. In Jython I don't think this exists as such, but using AtomicInteger and AtomicBoolean should ensure that no values are "out of date" in any thread.
Example usage:
In the SwingWorker constructor:
self.publication_counter_latch = CounterLatch()
In SW.publish:
# increase counter value BEFORE publishing chunks
self.publication_counter_latch.count_relative( len( chunks ) )
self.super__publish( chunks )
In SW.process:
# ... do sthg [HERE] with the chunks!
# AFTER having done what you want to do with your chunks:
self.publication_counter_latch.count_relative( - len( chunks ) )
In the thread waiting for chunk processing to stop:
worker.publication_counter_latch.await()
it seems to me that i get poor performance using the following SupervisedExecutor and ExecutorSuperviser implementation of my own, What do you think can be unefficient in this code? I want to learn how can i improve its effciency.
ExecutorSuperviser Class:
public class ExecutorSuperviser {
private SupervisedExecutor[] threadPool;
private int poolSize = 0;
private LinkedList<Runnable> q;\\my own implementation of linkedlist
public ExecutorSuperviser(int nThreads) {
threadPool=new SupervisedExecutor[poolSize=nThreads];
q=new LinkedList<Runnable>();
init();
}
public void execute(Runnable r) {
synchronized (q) {
q.addToTail(r);
}
for (int i=0;i<poolSize;i++)
if (!threadPool[i].isBusy()) {
if (!threadPool[i].isAlive()) threadPool[i].start();
threadPool[i].interrupt();
return;
}
}
private void init() {
for (int i=0;i<poolSize;i++) {
threadPool[i]=new SupervisedExecutor(this);
}
}
public Object getLock() {
return q;
}
public Runnable getTask() {
return q.removeHead();
}
public void terminate() {
for (int i=0;i<poolSize;i++)
threadPool[i].terminate();
}
public void waitUntilFinished() {
while (!isFinished()) {
try {
Thread.sleep(Thread.MAX_PRIORITY);
} catch (InterruptedException e) {}
}
}
private boolean isFinished() {
for (int i=0;i<poolSize;i++)
if (threadPool[i].isBusy()) return false;
return q.isEmpty();
}
}
SupervisedExecutor Class:
public class SupervisedExecutor extends Thread {
private boolean terminated = false;
private Boolean busy = false;
private ExecutorSuperviser boss;
SupervisedExecutor (ExecutorSuperviser boss) {
this.boss=boss;
}
public void run() {
while (!terminated) {
try {
sleep(MAX_PRIORITY);
} catch (InterruptedException e) {
synchronized (busy) {
busy=true;
}
Runnable r;
while (true) {
synchronized (boss.getLock()) {
r=boss.getTask();
}
if (r!=null) r.run();
else break;
}
synchronized (busy) {
busy=false;
}
}
}
}
public boolean isBusy() {
boolean isBusy;
synchronized (boss.getLock()) {
isBusy=busy;
}
return isBusy;
}
public void terminate() {
terminated=true;
}
}
How about the following solution which has the following advantages:
As a subclass of ThreadPoolExecutor, you don't have to re-implement everything which ThreadPoolExecutor does for you just to get the waitUntilFinished() functionality that you're after.
By taking advantage of ReentrantLock, Condition, and await()/signal() you avoid busy waiting, which can certainly hurt performance.
This implementation works by taking advantage of the beforeExecute() and afterExecute() methods which ThreadPoolExecutor exposes to keep our own count of active tasks. I don't use getActiveCount() because, according to the JavaDoc, it doesn't guarantee an exact answer (although perhaps in the case of ThreadPoolExecutor it does provide an exact answer, I'd need to research further to be sure).
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class WaitableThreadPoolExecutor extends ThreadPoolExecutor
{
private Condition waitCondition;
private ReentrantLock lock;
private int taskCount = 0;
public WaitableThreadPoolExecutor( int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue )
{
super( corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue );
lock = new ReentrantLock( );
waitCondition = lock.newCondition( );
}
// if isEmpty() is true, then there is no need to block
// otherwise, wait until waitCondition is signaled
public void waitUntilFinished( )
{
lock.lock( );
try
{
while ( !isEmpty( ) )
waitCondition.await( );
}
catch ( InterruptedException e )
{
e.printStackTrace();
}
finally
{
lock.unlock( );
}
}
// the ThreadPool is empty if our taskCount is 0 and the
// work queue is empty (this may not be bullet-proof, for one
// thing, I'm hesitant to use getActiveCount() because it
// does not guarantee an exact answer
protected boolean isEmpty( )
{
lock.lock( );
try
{
return taskCount == 0 && getQueue( ).isEmpty( );
}
finally
{
lock.unlock( );
}
}
// increment our task count before executing each task
#Override
protected void beforeExecute( Thread t, Runnable r )
{
super.beforeExecute( t, r );
lock.lock( );
try
{
taskCount += 1;
}
finally
{
lock.unlock( );
}
}
// decrement our task count after executing each task
// then, if the pool is empty, signal anyone waiting
// on the waitCondition
#Override
protected void afterExecute( Runnable r, Throwable t )
{
super.afterExecute( r, t );
lock.lock( );
try
{
taskCount -= 1;
if ( isEmpty( ) ) waitCondition.signalAll( );
}
finally
{
lock.unlock( );
}
}
public static void main( String[] args )
{
WaitableThreadPoolExecutor pool = new WaitableThreadPoolExecutor( 2, 4, 5000, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>( ) );
for ( int i = 0 ; i < 10 ; i++ )
{
final int threadId = i;
pool.execute( new Runnable( )
{
#Override
public void run( )
{
try { Thread.sleep( (int) ( Math.random( ) * 5000 ) ); } catch ( InterruptedException e ) { }
System.out.println( threadId + " done." );
}
});
}
pool.waitUntilFinished( );
System.out.println( "Done waiting." );
}
}
I included a simple main() method which you can use as a test case. It starts 10 threads which wait a random amount of time before printing that they are done. Then the main thread calls waitUntilFinished().
The results will look something like (the main point being that Done waiting. will always be printed last:
1 done.
2 done.
0 done.
4 done.
3 done.
5 done.
7 done.
8 done.
6 done.
9 done.
Done waiting.
Personally, I find using the plain ExecutorService shorter and easier.
Note: This is ALL the code you need.
ExecutorService es = Executors.newCachedThreadPool();
List<Future<Void>>futures = new ArrayList<Future<Void>>();
for (int i = 0; i < 10; i++) {
final int threadId = i;
futures.add(es.submit(new Callable<Void>() {
#Override
public Void call() throws InterruptedException {
Thread.sleep((int) (Math.random() * 1000));
System.out.println(threadId + " done.");
return null;
}
}));
}
for (Future<Void> future : futures)
future.get();
System.out.println("Done waiting.");
es.shutdown();
prints
2 done.
4 done.
7 done.
6 done.
8 done.
5 done.
9 done.
1 done.
3 done.
0 done.
Done waiting.