Solved

Thread priorities?

Posted on 2003-12-09
60
547 Views
Last Modified: 2010-03-31

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?
0
Comment
Question by:eire_ireland
  • 22
  • 18
  • 12
  • +1
60 Comments
 
LVL 35

Expert Comment

by:girionis
Comment Utility
 Use the join() method to do it.
0
 
LVL 86

Expert Comment

by:CEHJ
Comment Utility
You can do this using the wait-notify mechanism (see Sun thread tutorial) but i'm skeptical you need this in your project...
0
 

Author Comment

by:eire_ireland
Comment Utility
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.
0
 
LVL 35

Expert Comment

by:girionis
Comment Utility
 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.
0
 

Author Comment

by:eire_ireland
Comment Utility
In using the join() how do I target the thread that I want to wait for?
0
 
LVL 35

Expert Comment

by:girionis
Comment Utility
 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.
0
 

Author Comment

by:eire_ireland
Comment Utility
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
0
 
LVL 35

Expert Comment

by:girionis
Comment Utility
 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 :)
0
 
LVL 35

Expert Comment

by:girionis
Comment Utility
 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.
0
 

Author Comment

by:eire_ireland
Comment Utility
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?
0
 
LVL 86

Expert Comment

by:CEHJ
Comment Utility
>>This is what I want to do...

Why? Why not just wait until the process has finished and then draw the necessary conclusions?
0
 
LVL 35

Expert Comment

by:girionis
Comment Utility
 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.
0
 
LVL 86

Expert Comment

by:CEHJ
Comment Utility
(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
0
 

Author Comment

by:eire_ireland
Comment Utility
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.
0
 
LVL 35

Expert Comment

by:girionis
Comment Utility
  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();
    }
}
0
 
LVL 35

Expert Comment

by:girionis
Comment Utility
 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".
0
 
LVL 35

Expert Comment

by:girionis
Comment Utility
 ... also the getInt() method should't probably be synchronized :)
0
 
LVL 35

Expert Comment

by:girionis
Comment Utility
 ... and you obviously do not need the

while (result == 0)
{

  loop in the lock() method.
0
 
LVL 35

Expert Comment

by:girionis
Comment Utility
>  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();
}
0
 

Author Comment

by:eire_ireland
Comment Utility
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");
     
0
 
LVL 86

Expert Comment

by:CEHJ
Comment Utility
>>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.
0
 
LVL 35

Expert Comment

by:girionis
Comment Utility
 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.
0
 
LVL 92

Expert Comment

by:objects
Comment Utility
> 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
0
 

Author Comment

by:eire_ireland
Comment Utility
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);
          }
0
 
LVL 92

Expert Comment

by:objects
Comment Utility
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.
0
 

Author Comment

by:eire_ireland
Comment Utility
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
0
 
LVL 86

Expert Comment

by:CEHJ
Comment Utility
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?
0
 
LVL 92

Expert Comment

by:objects
Comment Utility
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();
   }
}

0
 

Author Comment

by:eire_ireland
Comment Utility
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();
 ^
0
 
LVL 92

Expert Comment

by:objects
Comment Utility
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.
0
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 

Author Comment

by:eire_ireland
Comment Utility
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();
0
 
LVL 92

Expert Comment

by:objects
Comment Utility
>  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.
0
 

Author Comment

by:eire_ireland
Comment Utility
What am i doing wrong?
0
 
LVL 92

Expert Comment

by:objects
Comment Utility
you're not handling the exception. you need to wrap the join's in a try/catch block.
0
 

Author Comment

by:eire_ireland
Comment Utility
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 )
 
0
 
LVL 92

Expert Comment

by:objects
Comment Utility
you need to catch InterruptedException, instead of IOException
0
 

Author Comment

by:eire_ireland
Comment Utility
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.
0
 
LVL 92

Expert Comment

by:objects
Comment Utility
add some deug in your client thread to see where its up to.
0
 

Author Comment

by:eire_ireland
Comment Utility
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?
0
 
LVL 86

Expert Comment

by:CEHJ
Comment Utility
>>
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.    
0
 
LVL 92

Expert Comment

by:objects
Comment Utility
> 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.
0
 

Author Comment

by:eire_ireland
Comment Utility
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?
0
 
LVL 92

Expert Comment

by:objects
Comment Utility
there is a close() method.
0
 

Author Comment

by:eire_ireland
Comment Utility
Im using the close method, but its not closing the streams

   input.close(); //this is closing
   output.close(); //not closing
   socket.close(); //not closing
0
 
LVL 92

Expert Comment

by:objects
Comment Utility
it should do, are you sure that code is being executed.
Add a debug println() call before it to check.
0
 

Author Comment

by:eire_ireland
Comment Utility
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.
0
 
LVL 92

Expert Comment

by:objects
Comment Utility
> each of the clients goes into an infinite loop outputting null

you need to determine why they are looping.
0
 

Author Comment

by:eire_ireland
Comment Utility
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");
             
                  }
0
 
LVL 92

Expert Comment

by:objects
Comment Utility
> while (true)

Why are you looping forever?
0
 

Author Comment

by:eire_ireland
Comment Utility
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
0
 
LVL 92

Expert Comment

by:objects
Comment Utility
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.
0
 

Author Comment

by:eire_ireland
Comment Utility
Could you elaborate a little , im fairly new to java....probably obvious
0
 
LVL 92

Expert Comment

by:objects
Comment Utility
Add a member variable to your client thread class and store the response recieved from the client in that variable.
0
 

Author Comment

by:eire_ireland
Comment Utility
Sending the result on the appropriate socket in each thread, how is this achieved if the threads have been closed??
0
 
LVL 92

Expert Comment

by:objects
Comment Utility
> 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.
0
 
LVL 86

Accepted Solution

by:
CEHJ earned 25 total points
Comment Utility
>>the socket being closed is though.

Hence my suggestion to keep the clients in a List so you can send the result to the right client. Having said that, i seem to remember a long time back that i mentioned keeping them in a map, which would be more convenient:

WhateverYourClientClassIsNow player1 = (WhateverYourClientClassIsNow)map.get("Player1");
Socket player1Socket = player1.getSocket();
// get stream and send message
0
 
LVL 92

Assisted Solution

by:objects
objects earned 25 total points
Comment Utility
No need for a Map or List you just need:

a.sendResults(...
b.sendResults(...

0
 

Author Comment

by:eire_ireland
Comment Utility
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
0
 
LVL 92

Expert Comment

by:objects
Comment Utility
0
 
LVL 86

Expert Comment

by:CEHJ
Comment Utility
8-)
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Suggested Solutions

For beginner Java programmers or at least those new to the Eclipse IDE, the following tutorial will show some (four) ways in which you can import your Java projects to your Eclipse workbench. Introduction While learning Java can be done with…
Basic understanding on "OO- Object Orientation" is needed for designing a logical solution to solve a problem. Basic OOAD is a prerequisite for a coder to ensure that they follow the basic design of OO. This would help developers to understand the b…
Viewers learn about the “while” loop and how to utilize it correctly in Java. Additionally, viewers begin exploring how to include conditional statements within a while loop and avoid an endless loop. Define While Loop: Basic Example: Explanatio…
Viewers will learn how to properly install Eclipse with the necessary JDK, and will take a look at an introductory Java program. Download Eclipse installation zip file: Extract files from zip file: Download and install JDK 8: Open Eclipse and …

763 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now