Reputation: 10995
I didn't think threading would be this difficult sigh. Anyways, the only way I could think of executing a function after a thread has completed is to use a static counter to increment whenever a thread ran.
if(++threadcounter==3){doSomething(); threadcounter =0;}
I found this wasn't a good idea because the threadcounter at times never reaches 4.
So I used atomic integer
if(atomicint.incrementAndGet()==4){doSomething(); atomicint.set(0);}
The counter is 5 or 0 and the app freezes. I don't know what's happening. How to use a correct counter? Thanks
EDIT:
Upvotes: 4
Views: 3454
Reputation: 17761
This is not an applicable solution to the problem check the comments!
You can either use Thread.join() to finish threads, or if you need some counter i'd recommend a volatile primitive like
volatile int threadCount=0;
which will guarantuee ordering and immediate writing to memory. check this page for an explanation of the volatile keyword
hope that helps
Upvotes: 0
Reputation: 47163
The simplest way to tackle this is with a good old-fashioned lock:
boolean shouldDoSomething;
synchronized {
++threadCounter;
if (threadCounter == 4) {
threadCounter = 0;
shouldDoSomething = true;
}
else {
shouldDoSomething = false;
}
}
if (shouldDoSomething) doSomething();
This will create contention on the lock, but over a very, very brief piece of code - a load, a store, and a few arithmetic instructions.
Your use of AtomicInteger
is wrong, because there is no locking or other concurrency control linking the incrementAndGet
and the set
, which means there is a potential race condition (value is 3, thread A increments to 4, thread B increments to 5, thread A sets to 0).
Upvotes: 5
Reputation: 48186
a better peice of code would be
if(atomicint.incrementAndGet()%5==0){doSomething();}
as long as it won't run over 2 billion times your fine
otherwize you can add a
int value;
if((value=atomicint.get())>=5)atomicint.compareAndSet(value,value%5);
after it but this won't be ideal as the compareandset can fail silently
or you can make you own incrementModAndGet
public static int incrementModAndGet(AtomicInteger atomicint, int mod){
int old,newval;
do{
old = atomicint.get();
newval = (old+1)%mod;
}while(!atomicint.compareAndSet(old,newval));
return newval;
}
Upvotes: 2
Reputation: 11818
Sounds like you're trying to execute some task, potentially generating a value, in another thread, and then in the initial thread make use of the generated value.
The Callable
interface is possibly what you want.
final Callable<Integer> task = new Callable<Integer>() {
@Override public Integer call() {
// do computation
return <some-integer>;
}
};
Future<Integer> future = Executors.newSingleThreadExecutor().submit(task);
// you can do other stuff here, in your thread. the task will be executing
Integer result = future.get();
Future#get
will block until the thread is complete.
Upvotes: 1
Reputation: 16142
Don't use AtomicInteger, it's not a good match to what you want to do. Use Thread.join to wait for a thread to terminate.
Upvotes: 3
Reputation: 5761
What kind of threading are you working with? Assuming a naive approach (where you just spin), you can just call the function immediately after it breaks out of the loop.
Perhaps if you posted some more code?
Upvotes: 0