synchronized threads not blocking each other - java

I'm not trying to fill the board with another of the same question, but I read about 15 solutions and nobody has quite the same issue. Here is the code I am looking at:
private AgentModel agent;
private UserModel user;
private int type;
public AgentThread(AgentModel agent, UserModel user, int type) {
this.agent = agent;
this.user = user;
this.type = type;
}
public void start() throws InterruptedException {
agent.setT(new Thread(this, agent.getID()));
agent.getT().start();
}
And a little bit down the way:
public void run() {
while (!agent.getT().isInterrupted()) {
agent.nextOP();
try {
if (agent.getOPS() > 0) {
agent.getT().sleep((long) (1000 / agent.getOPS()));
} else {
agent.getT().sleep(1000);
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
agent.getT().interrupt();
}
synchronized (user) {
agent.setState(agent.getT().getState().toString());
// System.out.println("Operations Completed: " +
// (1+agent.getOPCompleted()) );
if (type == 3) {
user.deposit(agent.getAmount(), Integer.valueOf(agent.getID()));
}
if (type == 4) {
user.withdraw(agent.getAmount(), Integer.valueOf(agent.getID()));
}
}
}
}
The agent object contains a thread that is started in the AgentThread start method. The AgentThread object takes in both the agent and the user and instances of their respective classes.
My problem is as follows: I'm setting the lock to be the instance of the UserModel class 'user'. The threads are supposed to either deposit or withdraw depending on their agent type.
When I execute agent.getT().getState(), it always returns RUNNABLE no matter how many instances of AgentThread I have created. Each AgentThread is given a new agent and a new thread but the same User object. It seems as though the threads are never blocking each other.
I know they are influencing the same user instance because I can output the changes detected by my listener and it reflects all running threads and their interactions with that user instance.
Every time a thread is started it enters an "infinite" loop where the user instance has a deposit or a withdrawal. These actions happen every x seconds.

You threads only lock the User object for enough time to perform a deposit() or withdraw() operation at intervals of, probably, hundreds of milliseconds. Unless deposit() or withdraw() are dependent on high latency external resources, they probably execute in a fraction of a microsecond, which would be enough for, say, thousands of lines of code. As a result, your chances of catching the system in a state where a thread has the User object locked are probably less than 1 in 100,000. In addition, for another thread to be blocked, it too would need to be trying to perform a deposit() or withdraw() operation. Given your likely parameters, the chances of such a collision are less than one in a million, which likely explains why you've never seen it.

When I execute agent.getT().getState(), it always returns RUNNABLE no matter how many instances of AgentThread I have created.
Right. This is because you are calling the agent.getT().getState() from inside of the thread itself. The thread will always see itself as RUNNABLE. When it is blocked or waiting, it isn't looking.
It seems as though the threads are never blocking each other.
No, as I read the code they are certainly blocking each other if they are working on the same User object. However, you are never calling agent.getT().getState() from another thread so it can see the BLOCKED or WAITING states.
One way to look at thread externally is by turning on JMX and using jconsole. If you go to the threads tab, you should be able to see the "Total blocked" and "Total waited" counts increase on your worker threads.
Every time a thread is started it enters an "infinite" loop where the user instance has a deposit or a withdrawal. These actions happen every x seconds.
I assume that's what you are expecting.

Related

synchronized keyword in Java threads

I am trying to see how multithreading(particularly with synchronized keyword) works.In this example I want the second thread abc1 to start executing after thread abc. So I've used synchronized keyword in run function.But the output line which says:
Initial balance in this thread is 10000
Initial balance in this thread is 10000
is what concerns me.Because the initial balance should be "-243000" as indicated in output line
Final balance after intial -243000 is 59049000
because the abc1 thread should wait for abc due to synchronized keyword.
Primarily , I want the threads to behave as if I write
abc.start
abc.join()
abc1.start()
abc1.join()
Here is my source code:
class parallel extends Thread{
account a;
public parallel(account a) {
this.a=a;
}
public synchronized void run() {
synchronized(this) {
System.out.println("Initial balance in this thread is "+a.amount);
long duplicate=a.amount;
boolean flag=true;
//System.out.println("Transaction inititated");
for(int i=0;i<10;i++) {
if(flag==true) {
//System.out.println("Deducting "+amount+"Rs from your account");
a.amount-=a.amount*2;
}
else {
//System.out.println("Depositing "+amount+"Rs from your account");
a.amount+=a.amount*2;
}
flag=!flag;
}
System.out.println("Final balance after intial "+duplicate+" is "+a.amount);
syncro.amount=a.amount;
}
}
}
class account{
public account(long rupe) {
amount=rupe;
}
long amount;
}
public class syncro {
static long amount;
public static void main(String[] args) throws InterruptedException{
//for(int i=0;i<10;i++) {
account ramesh=new account(1000);
parallel abc=new parallel(ramesh);
parallel abc1=new parallel(ramesh);
abc.start();
//abc.join();
abc1.start();
//abc1.join();
//}
//awaitTermination();
//Thread.sleep(4000);
boolean ab=true;
long cd=1000;
for(int i=0;i<10;i++) {
if(ab==true) {
//System.out.println("Deducting "+ab+"Rs from your account");
cd-=cd*2;
}
else {
//System.out.println("Depositing "+a+"Rs from your account");
cd+=cd*2;
}
ab=!ab;
}
//System.out.println("Final amount by multithreading is "+);
System.out.println("Final amount after serial order is "+cd);
}
}
You are mixing the creating of your own threads with the use of synchronized. Also, using synchronized(this) within a synchronized method is doing the same thing twice.
Synchronized is NOT about starting threads. It is about allowing only one thread to enter a certain block of code at a time.
Every object you create has a hidden field that you cannot read, but it does exist. It is of type Thread and it is called owner.
The synchronized keyword interacts with this hidden field.
synchronized (object) {
code();
}
means the following:
If object.owner == Thread.currentThread(), then just keep going and increment a counter.
If object.owner == null, then run object.owner = Thread.currentThread(), set that counter to 1, and keep going.
Otherwise (So, object.owner is some other thread), stop, freeze the thread, and wait around until the owner is set to null, and then we can go to option #2 instead.
Once we're in, run code(). When we get to the closing brace, decrement the counter. If it is 0, run object.owner = null.
Furthermore, all the above is done atomically - it is not possible for 2 threads to get into a race condition doing all this stuff. For example, if 2 threads are waiting for owner to become unset again, only one will 'get it', and the other will continue waiting. (Which one gets it? A VM impl is free to choose whatever it wants; you should assume it is arbitrary but unfair. Don't write code that depends on a certain choice, in other words).
A method that is keyworded with synchronized is just syntax sugar for wrapping ALL the code inside it in synchronized(this) for instance methods and synchronized(MyClass.this) for static methods.
Note that synchronized therefore only interacts with other synchronized blocks, and only those blocks for which the object in the parentheses is the exact same obj reference, otherwise none of this does anything. It certainly doesn't start threads! All synchronized does is potentially pause threads.
In your code, you've put ALL the run code in one gigantic synchronized block, synchronizing on your thread instance. As a general rule, when you synchronize on anything, it's public API - other code can synchronize on the same thing and affect you. Just like we don't generally write public fields in java, you should not lock on public things, and this is usually public (as in, code you don't control can hold a reference to you). So don't do that unless you're willing to spec out in your docs how your locking behaviours are set up. Instead, make an internal private final field, call it lock, and use that (private final Object lock = new Object();).

Variable 'runner' is not updated inside loop

Like this, I have two thread. The SleepRunner thread add some random numbers to a list then change flag to true and sleep. The main thread wait SleepRunner thread until the flag in SleepRunner object change from false to true then main thread will interrupte SleepRunner thread and the program will end.
But the question is, when the while loop is no body code in main thread, the variable 'runner' is not updated inside loop in other words The program is not over after SleepRunner thread change flag from false to true. So I tried to use debug tools in idea, but the program ended smoothly. And If I write some code, like System.out.println() or Thread.sleep(1) in while loop body at main thread, the program ended successfully too. it's too incredible! Does anyone know why this happens? Thanks.
public class Test1 {
public static void main(String[] args) {
SleepRunner runner = new SleepRunner();
Thread thread = new Thread(runner);
thread.start();
while(!(runner.isFlag())){
/*try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}*/
}
System.out.println("END");
thread.interrupt();
}
}
public class SleepRunner implements Runnable {
private boolean flag = false;
public boolean isFlag() {
return flag;
}
#Override
public void run() {
List<Integer> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
try {
Thread.sleep((long) (Math.random() * 200));
}
catch (InterruptedException e) {
System.out.println("Interrupted");
}
int num = (int) (Math.random() * 100);
System.out.println(Thread.currentThread().getName() + " " + num);
list.add(num);
}
flag = true;
System.out.println("30 Seconds");
try {
Thread.sleep(30000);
}
catch (InterruptedException e) {
System.out.println("Interrupted in 30 seconds");
}
System.out.println("sleep runner thread end");
}
}
You've violated the java memory model.
Here's how the JMM works*:
Each thread, whenever any field (from any object) is read or updated, flips a coin. On heads, it will make a copy and update/read from that. On tails, it won't. Your job is to ensure your code functions correctly regardless of how the coin lands, and you can't force the coinflip in a unit test. The coin need not be 'fair'. The coin's behaviour depends on the music playing in your music player, the whims of a toddler, and the phase of the moon. (In other words, any update/read may be done to a local cache copy, or not, up to the java implementation).
You may safely conclude that the only way to do it correctly, is to ensure the thread never flips that coin.
The way to accomplish that is to establish so-called 'comes before' relationships. Establishing them is done primarily by using synchronization primitives, or by calling methods that use synchronization primitives. For example, if I do this:
thread X:
synchronized(x) {
x.foo();
System.out.println(shared.y);
shared.y = 10;
}
thread Y:
synchronized(x) {
x.foo();
System.out.println(shared.y);
shared.y = 20;
}
then you've established a relationship: code block A comes before code block B, or vice versa, but you've at least established that they must run in order.
As a consequence, this will print either 0 10 or 0 20, guaranteed. Without the synchronized block, it can legally print 0 0 as well. All 3 results would be an acceptable result (the java lang spec says it's okay, and any bugs filed that you think this makes no sense would be disregarded as 'working as intended').
volatile can also be used, but volatile is quite limited.
Generally, because this cannot be adequately tested, there are only 3 ways to do threading properly in java:
'in the large': Use a webserver or other app framework that takes care of the multithreading. You don't write the psv main() method, that framework does, and all you write are 'handlers'. None of your handlers touch any shared data at all. The handlers either don't share data, or share it via a bus designed to do it right, such as a DB in serializable transaction isolation mode, or rabbitmq or some other message bus.
'in the small': Use fork/join to parallellize a giant task. The handler for the task cannot, of course, use any shared data.
read Concurrency in Practice (the book), prefer using the classes in the java.util.concurrent package, and in general be a guru about how this stuff works, because doing threading any other way is likely to result in you programming bugs which your tests probably won't catch, but will either blow up at production time, or will result in no actual multithreading (e.g. if you overzealously synchronize everything, you end up having all cores except one core just waiting around, and your code will actually run way slower than if it was just single threaded).
*) The full explanation is about a book's worth. I'm just giving you oversimplified highlights, as this is merely an SO answer.

Java Thread safety - Understanding the need of synchronization

I am having a very hard time trying to understand the concept of synchronizing methods, objects and understand the main issue of not doing so, when running a multi-threaded application.
I understand that synchronize keyword is used to make sure that only one thread will work with a specific object or enter a specific block or method in a time, basically locks it and unlocks when the execution ended, so the other threads can enter it.
But I don't really understand the problem, I am totally confused, I created a demo application, where I have 2 bank accounts, and one bank class which has 5000 funds and a method that transfers a specific amount of money to the given account, and in it's constructor it creates the 2 bank accounts and start the threads (each account is a thread).
Now in the bank account's class I have a funds field, and a run method which the thread will call upon start (the class inheriting Thread), and the run method will loop 10 times, and take 20 dollar from the main bank by calling Bank#takeFunds(int amount)
So there we go, the Bank class:
public class Bank {
private int bankmoney = 5000;
public Bank() {
Client a = new Client(this);
Client b = new Client(this);
a.start();
b.start();
}
public void takeMoney(Client c, int amount) {
if (bankmoney >= amount) {
bankmoney -= amount;
c.addFunds(amount);
}
}
public void print() {
System.out.println("left: " + bankmoney);
}
public static void main(String... args) {
new Bank();
}
}
And the Client class:
public class Client extends Thread {
private Bank b;
private int funds;
Random r = new Random();
public Client(Bank b) {
this.b = b;
}
public void addFunds(int funds) {
this.funds += funds;
}
public void run() {
for (int i = 0; i < 10; i++) {
b.takeMoney(this, 20);
}
System.out.println(Thread.currentThread().getName() + " : " + funds);
b.print();
}
}
And the output for me:
Thread-0 : 200
left: 4800
Thread-1 : 200
left: 4600
The program ends with 200$ in each account, and 4600 left in the bank, so I don't really see the issue, I am failing to demonstrate the issue of thread safety, and I think this is why I can't understand it.
I am trying to get the most simple explanation on how it works exactly, How can my code turn into a problem with thread safety?
Thanks!
Example:
static void transfer(Client c, Client c1, int amount) {
c.addFunds(-amount);
c1.addFunds(amount);
}
public static void main(String... args) {
final Client[] clients = new Client[]{new Client(), new Client()};
ExecutorService s = Executors.newFixedThreadPool(15);
for (int i = 0; i < 15; i++) {
s.submit(new Runnable() {
#Override
public void run() {
transfer(clients[0], clients[1], 200);
}
});
}
s.shutdown();
while(!s.isTerminated()) {
Thread.yield();
}
for (Client c : clients) {
c.printFunds();
}
}
Prints:
My funds: 2000
My funds: 8000
To start with, a thread is not an object. Do not assign a separate thread to each client. Threads do work and objects contain code which specifies what must be done.
When you call methods on a Client object, they do not execute "on that client's thread"; they execute in the thread from which they are called.
In order to make a thread do some work, you need to hand it over an object implementing the code to be executed on it. That's what an ExecutorService allows you to do simply.
Also keep in mind that locks do not "lock objects" and synchronized(anObject) will not on its own stop another thread from calling anObject's methods at the same time. Locks only prevent other threads trying to acquire the same lock from proceeding until the first thread is done with it.
I tested your program, and in fact got the following output:
(The result is not 4600 as in your case.)
The point is that just because it happens to work once doesn't mean that it will always work. Multi threading can (in an illsynchronized program) introduce non-determinism.
Imagine what would happen if your operations took a bit longer to execute. Let's simulate this with a Thread.sleep:
public void takeMoney(Client c, int amount) {
if (bankmoney >= amount) {
try { Thread.sleep(1000); } catch (InterruptedException e) { }
bankmoney -= amount;
c.addFunds(amount);
}
}
Now try running your program again.
your program is working fine , as you are only deducting total amount of 2000. Which is far lesser than initial value. So, this check has no play, you code will work even if you rmeove it.
if (bankmoney >= amount) {
The only bad thing that can happen in this scenario , if client1 checks that amount is more than he needs to withdraw , but in meantime other client withdraws it.
public void run() {
for (int i = 0; i < 100; i++) {
b.takeMoney(this, 200);
}
System.out.println(Thread.currentThread().getName() + " : " + funds);
b.print();
}
public void takeMoney(Client c, int amount) {
if (bankmoney >= amount) {
system.println("it is safer to withdraw as i have sufficient balance")
bankmoney -= amount;
c.addFunds(amount);
}
}
there will be time when client one will check bankmoney is greater than amount , but when he withdraws, it will reach to negative amount. as other thread will take that amount.
Run program, 4-5 times you will realize.
Let's look at a more realistic example and implement a transfer function for our Bank:
public boolean transfer(long amount, Client source, Client recipient) {
if(!source.mayTransferAmount(amount)) return false; // left as an exercise
source.balance -= amount;
recipient.balance += amount;
}
Now let's imagine two threads. Thread A transfers a single unit from Client x to Client y while Thread B transfers a single unit from Client y to Client x. Now you must know that without synchronization, you cannot be sure how the CPU orders operations, so it could be:
A: get x.balance (=100) to tmpXBalance
B: get x.balance (=100) to tmpXBalance
B: increment tmpXBalance (=101)
B: store tmpXBalance to x.balance (=101)
A: decrement tmpXBalance (=99)
A: store tmpXBalance to x.balance (=99)
(rest of exchange omitted for brevity)
Whoa! We just lost money! Client x won't be very happy. Note that locking alone won't give you any guarantee, you also need to declare balance as volatile.
Any time there's something you want to do to data that are shared by more than one thread, if it takes more than one step, then you probably need synchronization.
This takes three steps:
i++;
The steps are; (1) get the value of i from memory into a register, (2) add 1 to the register, (3) store the value of the register back into memory.
A running thread can be preempted at any time. That means, the operating system can pause it, and give some other thread a turn using the CPU. So, if there's no synchronization, thread A could perform step (1) of incrementing i (it could get the value into a register), and then it could be preempted. While thread A is waiting to run again, threads B, C, and D could each increment i a thousand times. Then when thread A finally got to run again, it would add 1 to the value that it originally read, and then store that back into memory. The three thousand increments by threads B, C, and D would be lost.
You need synchronization whenever one thread could put some data into a temporary state that you don't want other threads to see or operate on. The code that creates the temporary state must be synchronized, and any other code that could operate on the same data must be synchronized, and any code that merely allows a thread to see the state must synchronized.
As Marko Topolnik pointed out, synchronization doesn't operate on data, and it doesn't operate on methods. You need to make sure that all of the code that modifies or looks at a particular collection of data is synchronized on the same object. That's because synchronization does one thing, and one thing only:
The JVM will not allow two threads to be synchronized on the same object at the same time. That's all it does. How you use that is up to you.
If your data are in a container, it may be convenient for you to synchronize on the container object.
If your data are all instance variables of the same Foobar instance, then it may be convenient for you to synchronize on the instance.
If your data are all static, then you probably should synchronize on some static object.
Good luck, and have fun.

How to cancel all the thread/ threads in ExcecutorService?

I've written following multi thread program. I want to cancel the all the thread if one of the thread sends back false as return. However though I'm canceling the thread by canceling individual task. Its not working. What changes I need to make inorder to cancel the thread?
I've written following multi thread program. I want to cancel the all the thread if one of the thread sends back false as return. However though I'm canceling the thread by canceling individual task. Its not working. What changes I need to make inorder to cancel the thread?
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.Callable;
public class BeamWorkerThread implements Callable<Boolean> {
private List<BeamData> beamData;
private String threadId;
public BeamScallopingWorkerThread(
List<BeamData> beamData, String threadId) {
super();
this.beamData = beamData;
this.threadId = threadId;
}
#Override
public Boolean call() throws Exception {
Boolean result = true;
DataValidator validator = new DataValidator();
Iterator<BeamScallopingData> it = beamData.iterator();
BeamData data = null;
while(it.hasNext()){
data = it.next();
if(!validator.validateDensity(data.getBin_ll_lat(), data.getBin_ll_lon(), data.getBin_ur_lat(), data.getBin_ur_lon())){
result = false;
break;
}
}
return result;
}
}
ExecutorService threadPool = Executors.newFixedThreadPool(100);
List<Future<Boolean>> results = new ArrayList<Future<Boolean>>();
long count = 0;
final long RowLimt = 10000;
long threadCount = 1;
while ((beamData = csvReader.read(
BeamData.class, headers1, processors)) != null) {
if (count == 0) {
beamDataList = new ArrayList<BeamData>();
}
beamDataList.add(beamData);
count++;
if (count == RowLimt) {
results.add(threadPool
.submit(new BeamWorkerThread(
beamDataList, "thread:"
+ (threadCount++))));
count = 0;
}
}
results.add(threadPool.submit(new BeamWorkerThread(
beamDataList, "thread:" + (threadCount++))));
System.out.println("Number of threads" + threadCount);
for (Future<Boolean> fs : results)
try {
if(fs.get() == false){
System.out.println("Thread is false");
for(Future<Boolean> fs1 : results){
fs1.cancel(true);
}
}
} catch(CancellationException e){
} catch (InterruptedException e) {
} catch (ExecutionException e) {
} finally {
threadPool.shutdownNow();
}
}
My comments
Thanks all for your input I'm overwhelmed by the response. I do know that, well implemented thread takes an app to highs and mean time it a bad implementation brings the app to knees. I agree I'm having fancy idea but I don't have other option. I've a 10 million plus record hence I will have memory constraint and time constraint. I need to tackle both. Hence rather than swallowing whole data I'm breaking it into chunks and also if one data is invalid i don't want to waste time in processing remaining million data. I find #Mark Peters suggestion is an option. Made the changes accordingly I mean added flag to interrupt the task and I'm pretty confused how the future list works. what I understand is that looping through each field of future list starts once all the thread returns its value. In that case, there is no way to cancel all the task in half way from main list. I need to pass on the reference of object to each thread. and if one thread finds invalid data using the thread refernce call the cancel mathod of each thread to set the interrupt flag.
while(it.hasNext() && !cancelled) {
if(!validate){
// loop through each thread reference and call Cancel method
}
}
Whatever attempt you make to cancel all the remaining tasks, it will fail if your code is not carefully written to be interruptible. What that exactly entails is beyond just one StackOverflow answer. Some guidelines:
do not swallow InterruptedException. Make its occurrence break the task;
if your code does not spend much time within interruptible methods, you must insert explicit Thread.interrupted() checks and react appropriately.
Writing interruptible code is in general not beginner's stuff, so take care.
Cancelling the Future will not interrupt running code. It primarily serves to prevent the task from being run in the first place.
While you can provide a true as a parameter, which will interrupt the thread running the task, that only has an effect if the thread is blocked in code that throws an InterruptedException. Other than that, nothing implicitly checks the interrupted status of the thread.
In your case, there is no blocking; it's busy work that is taking time. One option would be to have a volatile boolean that you check at each stage of your loop:
public class BeamWorkerThread implements Callable<Boolean> {
private volatile boolean cancelled = false;
#Override
public Boolean call() throws Exception {
//...
while(it.hasNext() && !cancelled) {
//...
}
}
public void cancel() {
cancelled = true;
}
}
Then you would keep references to your BeamWorkerThread objects and call cancel() on it to preempt its execution.
Why don't I like interrupts?
Marko mentioned that the cancelled flag above is essentially reinventing Thread.interrupted(). It's a valid criticism. Here's why I prefer not to use interrupts in this scenario.
1. It's dependent on certain threading configurations.
If your task represents a cancellable piece of code that can be submitted to an executor, or called directly, using Thread.interrupt() to cancel execution in the general case assumes that the code receiving the interrupt will be the code that should know how to cleanly cancel the task.
That might be true in this case, but we only know so because we know how both the cancel and the task work internally. But imagine we had something like this:
Task does piece of work
Listeners are notified on-thread for that first piece of work
First listener decides to cancel the task using Thread.interrupt()
Second listener does some interruptible piece of work, and is interrupted. It logs but otherwise ignores the interrupt.
Task does not receive interrupt, and task is not cancelled.
In other words, I feel that interrupt() is too global of a mechanism. Like any shared global state, it makes assumptions about all of the actors. That's what I mean by saying that using interrupt() exposes/couples to details about the run context. By encapsulating it in a cancel() method applicable only for that task instance, you eliminate that global state.
2. It's not always an option.
The classic example here is an InputStream. If you have a task that blocks on reading from an InputStream, interrupt() will do nothing to unblock it. The only way to unblock it is to manually close the stream, and that's something best done in a cancel() method for the task itself. Having one way to cancel a task (e.g. Cancellable), regardless of its implementation, seems ideal to me.
Use the ExecutorService.shutdownNow() method. It will stop the executor from accepting more submissions and returns with the Future objects of the ongoing tasks that you can call cancel(true) on to interrupt the execution. Of course, you will have to discard this executor as it cannot be restarted.
The cancel() method may not terminate the execution immediately if the Thread is not waiting on a monitor (not blocked interruptibly), and also if you swallow the InterruptedException that will be raised in this case.

Can Java's CountDownLatch be used from a passive class rather than a thread?

So I am working on this program that simulates a day at work and each worker is its own thread. I'm trying to implement meetings where the workers attend meetings but the meetings do not start until everyone that is supposed to be at the meeting has arrived. So I have this method for attending the meeting.
public void attendMeeting(Employee worker){
this.cdStart.countDown();
worker.meetingWait();
try {
this.cdStart.await();
worker.meetingStart(this.length);
if(this.attendees.get(0).equals(worker)){
this.room.exit();
} // end if
} // end try
catch (InterruptedException err) {
// Do Nothing
} // end catch
} // end method attendMeeting
The worker parameter being an instance of the Employee class that extends Thread and this.cdStart is the CountDownLatch. However, when running this with a meeting of four employees, only one employee seems to be able to get in, decrement the count, and hit the await() call. None of the other worker threads seem to be able to enter it. I did notice that a lot of the online examples of use pass the CountDownLock object to the threads themselves to handle. Is there a reason why this would not work instead?
I am assuming you are having a single thread pass in an Employee Thread object. That single thread will be waiting indefinitely until the N number of parties arrive (you need an individual thread for each Employee instance aside from the Employee thread). This means that if only one thread is continuously passing the Employee/Thread you will never get more then one Employee waiting at the meeting.
This thread should instead, at best, signal the Employee threads to attend the Meeting.
You should have the latch in the Meeting class and have them await on that latch. This also requires a slight restructure of the way it works.
You pass the Meeting instance into the Employee to have that thread wait.
public Employee extends Thread{
//define this at some point whether in constructor or a
//means of notifying the thread to attend the meeting
private Meeting meeting;
public void run(){
//do some stuff until this employee is ready to go to a meeting
meeting.waitForAllOthersToArrive();
}
}
public class Meeting{
CountDownLatch latch = new CountDownLatch(numberOfEmployees);
public void waitForAllOthersToArrive(){
latch.countDown();
latch.await();
}
}
What I would suggest for this however is a CylicBarrier. Though you wouldn't be re using it, the way the CyclicBarrier works fits better what you're trying to do, the Meeting class would then look like
public class Meeting{
CylicBarrier barrier = new CylicBarrier(numberOfEmployees);
public void waitForAllOthersToArrive(){
barrier.await(); //when await() is called numberOfEmployees then all waiting threads will awake
}
}

Categories

Resources