Link to home
Start Free TrialLog in
Avatar of eire_ireland
eire_ireland

asked on

Thread priorities?


There are two threads that have been started. Thread one is executing, when this thread encounters a certain line of code pause execution until the other thread completes execution, then finish execution of the thread that has been paused. Is there any way of doing this?
Avatar of girionis
girionis
Flag of Greece image

 Use the join() method to do it.
You can do this using the wait-notify mechanism (see Sun thread tutorial) but i'm skeptical you need this in your project...
Avatar of eire_ireland
eire_ireland

ASKER

Well I think I do, because both threads are calling the same function. The return value of the function depends on the second thread that has started. So I want the first thread to wait until the second thread has called the function before I call the function in the first thread.
 Take a look here and tell me if it helps: http://javaalmanac.com/egs/java.lang/IfStopped.html otherwise I will try to post some sample code.
In using the join() how do I target the thread that I want to wait for?
 If the thread that does the reading is called readingThread then when you find the line just do:

  readingThread.join();

 and this should work. It should wait for the other thread to finish before it goes on again.
This is what I want to do

thread one
wait until thread two has got return value then
get return value from function

thread two
get return value from function
 Alternative you can go with CEHJ's solution. Have the reading thread wait and when then other thread finishes call notifyAll and this should get the reading thread started again.

  I suggest you use join though, after all that's what it is here for :)
 ok in a nutshell this could be:

Thread t1 = new Thread();
Thread t2 = new Thread();

t1.start();
t2.start();
...
if (lineFound)
{
   t1.join();
}

  About reading the return value. YOu can have an instance variable (synchronize it) that will be set to a value when thread two (t2)finishes... after that t1 can read it and proceed normally.
The thread im waiting for to finish is the second thread so the name of that thread is not set until it begins, how can I use the join method in the first thread?
>>This is what I want to do...

Why? Why not just wait until the process has finished and then draw the necessary conclusions?
 If you want to wait for the second thread to finish then you need to call join on the second thread. join() always waits for the calling thread to finish before going further.
(assuming your current project)

Player1 sends "rock" and its name
Player2 sends "scissors" and its name

Having received two messages, server declares Player1 the winner
I did try something like that CEHZ but it didnt work, I think the join way might work but its not recognising my thread names. Im using setName to name the thread and nameofthread.join() but its throwing an error.
  eire_ireland do you want the second thread to start simultaneously with the first thread or after the first thread has joined?

  If you do t1.join() then the first thread will finish what it's doing and then you can start the second one. If you start both threads at the same time and you use join() you run the risk of one thread finishing before join is ever getting called so join() will simply return.

  I have written a very quick and simpl example using wait and notify as suggestedoriginally by CEHJ. I adapted the Thread example of the java threa tutorial, maybe you will be able to modify it to obtain what you want. The programme simply runs two threads "Blue" and "Red" and at some point the Blue thread waits for the Red thread to finish. The Red thread does a dummy calculation of a variable (I call it "result") and then it sets it to the result of a multiplication. The Blue thread then goes on and access it and displays it on the screen.


class Blue extends Thread {

      private ThreadSwitch ts;
      
    public Blue(String str, ThreadSwitch ts) {
        super(str);
        this.ts=ts;
    }
   
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(i + " " + getName());
            try {
                  if (i==5)
                  {
                        System.out.println(getName() + " is waiting till other thread finishes");
                        ts.lock();
                  }
                       sleep((long)(Math.random() * 2000));
            } catch (InterruptedException e) {}
        }

        System.out.println("DONE! " + getName());
        System.out.println("Result is: " + ts.getInt());
    }
}

class Red extends Thread {
      private ThreadSwitch ts;
      
    public Red(String str, ThreadSwitch ts) {
        super(str);
        this.ts=ts;
    }
   
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println(i + " " + getName());
            try {
                       sleep((long)(Math.random() * 2000));
            } catch (InterruptedException e) {}
        }

        System.out.println("DONE! " + getName());
        ts.setInt(6*3);
    }
}

class ThreadSwitch
{
      public int result = 0;
      
      public synchronized void lock()
      {
            while (result == 0)
            {
                  try
                  {
                        wait();
                  }
                  catch(InterruptedException ie)
                  {
                        System.err.println(ie);
                  }
            }
            notify();
      }
      
      public synchronized void setInt(int i)
      {
            notify();
            result = i;
      }
      public synchronized int getInt()
      {
            notify();
            return result;
      }
}

public class ThreadTest {
    public static void main (String[] args) {
          ThreadSwitch ts = new ThreadSwitch();
      
              Thread t1 = new Blue("Blue", ts);
              Thread t2 = new Red("Red", ts);
              t1.start();
              t2.start();
    }
}
 The ThreadSwitch class is the class that holds the lock on the "result" variable. Apart from that it is also used to set and get the value of the "result".
 ... also the getInt() method should't probably be synchronized :)
 ... and you obviously do not need the

while (result == 0)
{

  loop in the lock() method.
>  loop in the lock() method.

  meant block of code in the lock method. Simply do:

public synchronized void lock()
{
               try
               {
                    wait();
               }
               catch(InterruptedException ie)
               {
                    System.err.println(ie);
               }

          notify();
}
This is how im defining my threads. I cant really take a whole lot from the code you posted, I dont think its what i have in mind. This is of the code im using and Im trying to do is commented.

  public FirstClient(Socket socket) {
     this.socket = socket;
     start();
   }
   public void run()
   {    try
        {
 //I want the thread to go this far and then stop until the second thread (SecondClient below) fully executes.

                           if(num == 1){
                                 output = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);
                             output.println("You have lost");
 

   public SecondClient(Socket socket) {
     this.socket = socket;
     start();
   }
   public void run()
   {    try
        {
             
                           if(num == 1){
                                 output = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);
                             output.println("You have won");
     
>>I did try something like that CEHZ but it didnt work

It's not generally a good idea, if you can't get something simple working, to try something more complex in the hope that it'll fix things.

I see no reason to do anything other than wait until the two players have taken their turns and then inform them of the outcome. There is no reason for synchronization of threads in the way you imagine.
 You do not need to take a whole lot from the code I posted, just the principle of it, how to make a thread wait while another one is executing. Just run my code (copy/paste it), see if it is something you need and then you can adjust the principles in your application.
> This is of the code im using and Im trying to do is commented.

In that case join() won't help (unless you handle clients a little differently).
You need to use wait()/notify() in your threads similiar to the example girionis has posted above. Where your client thread would do something like:

- read value from user
- wait
- send outcome

And in the server notify clients once values recieved from both users
Generally maybe, but this way ive output going to the second client informing of the outcome. returnval(a var in the code below - num in the previous post is returnval) is initially set to zero when the firsts client calls it. But this value may be changed by the second client which is why I want to call the below function in the first client after the second client executes. I can see no reason why this wont work if a method is put forward that does what im asking?

 public int StoreChoice(String Choise1, int flag, int thr)
          {
                              int returnval = 0;                
                        if (thr == 2){
                        Choisetwo = Choise1;
                         display.append("\n\n First Player to connect sent" +Choiseone);
                
                             display.append("\n\n Second Player to connect sent" +Choisetwo);
                                   if(Choiseone.equals("Rock") && Choisetwo.equals("Paper")){
                                  returnval = 1;
                                  display.append("\n\nIn checking");
                       
                            
             return(returnval);
          }
your problem is that your client threads need to wait for the all input to become available, and then by notified when it is available so they can proceed.
I was trying that earlier and came up with this but the display methods didnt get executed?

public class Serverz extends Frame
{
   String Choiseone;//declared gloablly
   String Choisetwo;//declared globally

   else if (ClientsConnected == 1)
     new FirstClient(serve.accept());
       
      else if (ClientsConnected == 2){
         new SecondClient(serve.accept());

display.append("\n\n First Player to connect sent" +Choiseone);
display.append("\n\n Second Player to connect sent" +Choisetwo);

//Choiseone and Choisetwo got here
Perhaps, for clarification, you can tell us, without using any technical language, what you want the sequence of events to be, message-wise, among the participants?
Here's an outline of what is needed:

You client thread needs to do something like this (where server is a reference to Serverz instance that started the thread):

public void run()
{
   // read input from user

   server.setResult(answer);

   String result = server.getResult();

   // send result to server
}

For a single game your server then just needs to start the two threads:

a = new FirstClient(serve.accept());
b = new SecondClient(serve.accept());


public void setResult(String result)
{
   // store results

   if (input recieved from both clients)
   {
      // all input recieved, so notify waiting thread

      notifyAll();
   }
   else
   {
      // have not recieved input from other palyer so wait until it comes in
      wait();
   }
}

I think this could work but its throwing an error:

try{

FirstClient a = new FirstClient(serve.accept());
SecondClient b = new SecondClient(serve.accept());

// wait for thread to finish

a.join();
b.join();
display.append("\n\n First Player to connect sent" +Choiseone);
display.append("\n\n Second Player to connect sent" +Choisetwo);

}
   catch( IOException e )
  {
   e.printStackTrace() ;
  }

C:\Documents and Settings\Adrian Ron\Desktop\Serverz.java:74: unreported exception java.lang.InterruptedException; must be caught or declared to be thrown
a.join();
 ^
C:\Documents and Settings\Adrian Ron\Desktop\Serverz.java:75: unreported exception java.lang.InterruptedException; must be caught or declared to be thrown
b.join();
 ^
Problem with using join() is that you don't get opportunity to send the result back to the client as the client thread would have alreay completed.
Objects : this is code I got off you a few days ago for a different problem, I didnt use it then but it compiled fine, is there a difference?

Comment from objects
Date: 12/07/2003 01:06PM PST
      Comment       

> is there a way of waiting until the two threads have executed

yes, if thats what you want to do.

FirstClient a = new FirstClient(serve.accept());
SecondClient b = new SecondClient(serve.accept());

// wait for thread to finish

a.join();
b.join();
>  I didnt use it then but it compiled fine, is there a difference?

The InterruptedException exception must have been being handled by that code block previously.

When I suggested that I was not aware you needed to return the result to client.
What am i doing wrong?
you're not handling the exception. you need to wrap the join's in a try/catch block.
Ive tried this but its throwing the same error, could it be my jdk?

try{
a.join();
b.join();
}
 catch( IOException e )
  {
   e.printStackTrace() ;
  }  

--------------------Configuration: j2sdk1.4.0_02 <Default>--------------------
C:\Documents and Settings\Adrian Ron\Desktop\Serverz.java:75: unreported exception java.lang.InterruptedException; must be caught or declared to be thrown
a.join();
 ^
C:\Documents and Settings\Adrian Ron\Desktop\Serverz.java:76: unreported exception java.lang.InterruptedException; must be caught or declared to be thrown
b.join();
 ^
C:\Documents and Settings\Adrian Ron\Desktop\Serverz.java:78: exception java.io.IOException is never thrown in body of corresponding try statement
 catch( IOException e )
 
you need to catch InterruptedException, instead of IOException
thats it, cheers, its still not executing the code although, after the joins... Im closing input and output streams for each thread so the threads should be finishing up.
add some deug in your client thread to see where its up to.
just something I noticed there, if im closing up each client thread after they have sent their choice how am I going to send the result (based on the choice) to each client?
>>
Player1 sends "rock" and its name
Player2 sends "scissors" and its name
Having received two messages, server declares Player1 the winner
>>

...sending the result on the appropriate socket, having saved them in a list.    
> how am I going to send the result (based on the choice) to each client?

that was mentioned above. thayts why join() is not approriate with your current architecture. Either use wait()/notify() as I outlined above, or move the code that returns the results to the client out of your clients run() emthod into it's own.
I'd suggest the wait/notify approach.
output and socket streams are not closing. Output sends a string to the server, iand socket is just a socket connection. any other way to close them?
there is a close() method.
Im using the close method, but its not closing the streams

   input.close(); //this is closing
   output.close(); //not closing
   socket.close(); //not closing
it should do, are you sure that code is being executed.
Add a debug println() call before it to check.
The sockets werent closing in a try but now they are, moved the close statements:

 //reading choice sent by client
                       readChoice = input.readLine();
                       display.append(readChoice);
                       output = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);      
           
                      num = StoreChoice(readChoice, 2 , 1 , 0 , "");
                           display.setText("\n\n Input");
                             input.close();
                    output.close();
                    display.append("\n\n Output");
                    socket.close();
                    display.append("\n\n Socket");
 
The following code from earlier now works
a.join();
b.join();
display.append("\n\n First Player to connect sent" +Choiseone);
display.append("\n\n Second Player to connect sent" +Choisetwo);

But the each of the clients goes into an infinite loop outputting null, is it ok to close the sockets like this?, the append commands output the correct values entered by the user.
> each of the clients goes into an infinite loop outputting null

you need to determine why they are looping.
This is why, im closing sockets in a while loop, a silly mistake, if I take the closing methods out of the while loop a compile error saying the statements are not reachable is thrown. If I put the closing methods into a "finally" they dont get executed. What can I do?

while (true)
                  {
                       //reading choice sent by client
                       readChoice = input.readLine();
                       display.append(readChoice);
                       output = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()), true);
                       //table.put(threadName, String);
                       addString(getName(), readChoice);
                       input.close();
                  display.setText("\n\n Input");
                    output.close();
                    display.append("\n\n Output");
                    socket.close();
                    display.append("\n\n Socket");
             
                  }
> while (true)

Why are you looping forever?
I should'nt be doin that, I think its fixed now anyway, just to do this:

Player1 sends "rock" and its name
Player2 sends "scissors" and its name
Having received two messages, server declares Player1 the winner
>>

...sending the result on the appropriate socket, having saved them in a list.    

How do I save to a list, I know its another question, ill increase the points
Theres no need to save them in a list, (and not really appropriate either).
Just have each client remember the answer recieved, and the server can then get the answers directly from client instances.
Could you elaborate a little , im fairly new to java....probably obvious
Add a member variable to your client thread class and store the response recieved from the client in that variable.
Sending the result on the appropriate socket in each thread, how is this achieved if the threads have been closed??
> how is this achieved if the threads have been closed??

the thread ending is not a problem. the socket being closed is though.
If you still need to communicate with the client then your run() method shouldn't close the connection.

Then add new method to your client thread class that sends the results to the client using the still open connection.
ASKER CERTIFIED SOLUTION
Avatar of CEHJ
CEHJ
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Ive went in a different direction, its working at least, to stop one of the threads from executing i used a while loop waiting for the other thread to initialise a variable, when the variable got initialised the other thread had completed so the first could now complete.

I did try using a map but it seemed to go back to the same problem that I was trying to initially solve.
Using global variables is really what has gotten me out of this problem.

The help was good.
Thanks
8-)