5

I have a button "addCashier" which is creating a thread called "Cashier" now this thread is just simply generating orders every 4 seconds, a while(true) loop in the run() method of the thread. All is good there, but now I want to add a button to simulate cashiers logging off. I added a boolean variable to my while loop onDuty and a public function logOff() which sets this onDuty bool to false to get me out of the run's while loop. My problem now is from my gui class how can I call a function on a specific thread? Each cashier thread has been generated at runtime so I don't know their names.

I hope I made sense. Thanks in advance.

mikeyP
  • 237
  • 1
  • 2
  • 8
  • It depends how you created the thread. Can you reference it through an array? – Nick Brunt Oct 16 '11 at 18:22
  • hmmm I didn't know you could store thread objects in an array I'll take a look at that approach. – mikeyP Oct 16 '11 at 18:23
  • @mikeyP - you could also keep them in a `HashMap`; you mention something about them having "names" which would be the (`String`) keys. – Brian Roach Oct 16 '11 at 18:30
  • @BrianRoach Ok, that makes sense I like the Hash implementation, but what would the thread reference be would it be myThread in this bit of code: `Thread myThread; Cahier (String name) { myThread = new Thread( this ); myThread.start(); }` – mikeyP Oct 16 '11 at 18:34
  • @mikeyP, thats correct - `myThread` is your reference - but you also need to set the name of the `Thread` explicitly by calling `setName(String name)` method on your `Thread` reference for each thread you create. Then add the two ( the name and the reference ) into a HashMap. Use the `Name` as your handle to get your thread later to stop the particular thread. – Bhaskar Oct 16 '11 at 18:39
  • @Bhaskar ok cool, I can just throw it the Cashier name I receive from my textfield as a variable. that's awesome. I'm hash mapping away now :) – mikeyP Oct 16 '11 at 18:57

4 Answers4

10
Thread t = CashierThread();  //keep the reference to thread somewhere...

Now instead of a boolean property use built-in interrupted flag:

public void run() {
  while(!Thread.currentThread().isInterrupted()) {
    //...
  }
}

When you want to turn of the thread by clicking on a button simply call:

t.interrupt();

Of course you need to have access to t variable from the client code.

Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
  • +1: While correct, I would just go for the shorter `while(!Thread.interrupted())` assuming I am just going to exit the thread. – Peter Lawrey Oct 16 '11 at 18:25
  • While this is one way to stop a thread, it doesn't do anything over his existing boolean solution. His real problem is that he isn't keeping track of his threads and doesn't know how to get to them to stop them. – Brian Roach Oct 16 '11 at 18:27
  • ok thanks Tomasz and others.. just trying to work out how to get this thread reference now. – mikeyP Oct 16 '11 at 18:28
  • @TomaszNurkiewicz if I did something like `Thread myThread; Cahier (String name) { myThread = new Thread( this ); myThread.start(); }` Would myThread be the reference? – mikeyP Oct 16 '11 at 18:30
  • 1
    @BrianRoach: agree, so I guess my first comment: *keep the reference to thread somewhere* actually answers the question. The rest is actually an advice not to use hand-made flags (and avoid synchronization/volatile pitfalls). But I see now that other answers recommending map data structure are a bit more accurate, upvoting them now :-). – Tomasz Nurkiewicz Oct 16 '11 at 18:32
  • but OP is still happy selecting this as his answer ! – Bhaskar Oct 16 '11 at 18:43
  • @mikeyP: Yes, `myThread` is the reference to the thread. I assume you either extend a `Thread` or implement `Runnable` and pass it to the `Thread`'s c-tor. In both cases you simply call `myThread.interrupt()`. – Tomasz Nurkiewicz Oct 16 '11 at 18:57
  • Watch out for Thread.interrupted() this is a static method, which gets and clears the interrupted flag ! you better use Thread.currentThread().isInterrupted() – Radu Toader Jun 24 '15 at 18:30
  • @RaduToader if you control the thread and this `run` method is all the thread will ever do, then it doesn't matter if you clear the flag because the thread will terminate after being interrupted anyway – kbolino Jul 20 '16 at 01:27
1

You can store each thread's reference into a HashMap - along with its id or Name as the key. Later when you want to deal with one particular Cashier thread , use the Name or id to fetch the corresponding Thread from the HashMap and call the appropriate logOff() method on it.

Bhaskar
  • 7,443
  • 5
  • 39
  • 51
1

If collecting the reference to all the threads is a problem, One other way could be having a public static synchronized HashMap that has the threadId(random number assigned at runtime to each thread) as the key and the boolean as the value. You can modify the while loop to pick the corresponding boolean value from this centralized Map. This would let you log-off a particular cashier.

Vivek Viswanathan
  • 1,968
  • 18
  • 26
1

You can keep a reference of the Thread object somewhere so that u can call threadObj.logOff()

If you are not willing to do that then while creating a thred u can assign a unique name to the thread.

public void run ()
{
    this.setName(strCashireID);
    ......
}

At runtime, u can get the thread by:

Thread getThread(String strCashireID) {
   ThreadGroup threadGroup = Thread.currentThread( ).getThreadGroup( );
   Threads[] threads = new Thread[ threadGroup.activeCount() ];
   threadGroup.enumerate(threads);
   for (int nIndex=0; nIndex<threads.length; nIndex++) {
      if(threads[nIndex] != null && threads.getName().equals(strCashireID) {
         return threads[nIndex];
      }
   }
   return null;
}

I'll still suggest that u store the thread objects in a hash map instead of enumerating them at runtime.

PC.
  • 6,870
  • 5
  • 36
  • 71