Multiple thread question.

I almost understand this but I'm still not totally clear.

I have multiple classes that implement Runnable.

Objects of these classes are created in a class that has main().

I create a thread for each of these objects inside main().

But, what happens is that the threads execute one at a time, in other words, only one runs at a time.

I want to have them run consecutively. What do I need to do?

[438 byte] By [joseph_mueller] at [2007-9-26 2:15:13]
# 1
One more thing... do I need to use "synchronized"?
joseph_mueller at 2007-6-29 9:12:07 > top of Java-index,Archived Forums,Java Programming...
# 2

By "consecutively" you don't mean consecutively, do you? Because that's what you say is happening, they are running one at a time. It's more likely that you want them to run simultaneously, that is, all at the same time.

Anyway, after you get your vocabulary straightened out, you need to tell us how you are causing them to run.

DrClap at 2007-6-29 9:12:07 > top of Java-index,Archived Forums,Java Programming...
# 3
my guess is you are starting the threads by invoking the run() method that you wrote for your thread classes.if that is the case, you have to start a thread by invoking the start() method.
parthasarkar at 2007-6-29 9:12:07 > top of Java-index,Archived Forums,Java Programming...
# 4

OK. Why don't we try this code. If I want to have control switch back and forth from each thread so the console prints 1 2 3 4 etc... what do I need to change? Right now, it first prints the even numbers, then it prints the odd numbers.

class Threads implements Runnable{

public static void main(String argv[]){

Threads tc1= new Threads();

testClass2 tc2 = new testClass2();

Thread thread1 = new Thread(tc1);

Thread thread2 = new Thread(tc2);

thread2.start();

tc2.printEvens();

tc1.printOdds();

}

void printOdds(){

//print ODD numbers up to 9

for(int index=1; index<=9; index+=2){

System.out.println(index);

}

}

public void run(){

//

}

}

class testClass2 implements Runnable{

void printEvens(){

//prints EVEN number up to 10

for(int index=0; index<=10; index+=2){

System.out.println( index );

}

}

public void run(){

//

}

}

joseph_mueller at 2007-6-29 9:12:07 > top of Java-index,Archived Forums,Java Programming...
# 5

change the code as shown.

class Threads implements Runnable{

public static void main(String argv[]){

Threads tc1= new Threads();

testClass2 tc2 = new testClass2();

Thread thread1 = new Thread(tc1);

Thread thread2 = new Thread(tc2);

thread2.start();

thread1.start();

}

void printOdds(){

//print ODD numbers up to 9

for(int index=1; index<=99; index+=2){

try{

Thread.sleep(100);

}catch(Exception e){}

System.out.println(index);

}

}

public void run(){

printOdds();

}

}

class testClass2 implements Runnable{

void printEvens(){

//prints EVEN number up to 10

for(int index=0; index<=100; index+=2){

try{

Thread.sleep(100);

}catch(Exception e){}

System.out.println( index );

}

}

public void run(){

printEvens();

}

}

u should wrote all u threading code in the run method.

I have also increased the count to 100 and added a delay. It increases the execution time of the thread.

otherwise one thread executes to completion before the second thread starts.

stephen_edward at 2007-6-29 9:12:07 > top of Java-index,Archived Forums,Java Programming...
# 6
Thank you for your reply. You call the method from inside run(). I should have recognized that.Thanks again.
joseph_mueller at 2007-6-29 9:12:07 > top of Java-index,Archived Forums,Java Programming...
# 7

First of all, you haven't called start on thread1, so only thread2 will be running anyway.

Secondly, you call printEvens and printOdds outside of the run methods, so they execute as if there were no threads involved anyway. When you call start on a Thread, the code that runs in its own thread is the run method.

Alter the code to look like this:

public static void main(String[] argv)

{

...

thread1.start();

thread2.start();

//Don't call printEvens or printOdds here.

}

public void run()

{

printOdds();

//call printEvens in testClass2

}

However, you should be aware that it is very unlikely the code will print odd, even, odd, even... (and won't do the same from run to run or on different platforms) as the threads are time-sliced by the operating system, and different operating systems use different methods to divide time between threads.

You can call sleep as Stephen suggested, but I don't like that method - technically you still can't be sure it will run as you wish - other threads running on the same machine (for example Windows runnin in the background) can take up processor time and after a couple of hundred milliseconds your threads might both have come out of their sleep without continuing execution, and any one of them could continue first.

To make one thread more likely to be chosen over another, you can change their priorities and call yield after each iteration throught the for loop, but its still up to the operating system in the end - in short, as far as I'm aware, you can NEVER be sure of the order in which threads will be called without limiting yourself to a paricular platform that explicitely states how multiple threads will share processor time.

I think (but its a long time since I looked it up) that Windows operates a system wherby threads of the same priority are (randomly) chosen for execution, and threads with higher priorities are more likely (not guaranteed) to get more processor time. On the other hand, Unix machines operate a round-robin, whereby all threads of the same priority get the same amount of processor time and are allocated time in a strict order according to when they were started, and higher priority threads always take precedence).

mattbunch at 2007-6-29 9:12:07 > top of Java-index,Archived Forums,Java Programming...
# 8

Using semaphores you can gaurentee the order the threads operate. Basically, you give each thread a semaphore for itself, and the other thread. Then when the threads run, the first .P() (sleep) is ignored for thread1 (because of the value set in the constructor)while thread2 sleeps. At the bottom of the loop thread1 tells tread2 to wake up .V(), then it puts itself to sleep while thread2 runs. This continues until countTo is reached.

-Mike

file: TestClass1.java

public class TestClass1 implements Runnable{

int counter = 0;

int countTo;

Semaphore tc1_P;

Semaphore tc2_V;

public static void main(String argv[]){

int count = 10; //this determines how high to count.

//the parameter of the semaphore constructor == 1

//indicates the first .P() (sleep) will be ignored

Semaphore S1 = new Semaphore(1);

//the parameter of the semaphore constructor == 0

//indicates the first .P() (sleep) will put the thread to sleep.

Semaphore S2 = new Semaphore(0);

Thread thread1 = new Thread(new TestClass1(count, S1, S2));

Thread thread2 = new Thread(new TestClass2(count, S1, S2));

thread1.start();

thread2.start();

}

TestClass1(int count, Semaphore tc1_P, Semaphore tc2_V)

{

this.countTo = count;

this.tc1_P = tc1_P;

this.tc2_V = tc2_V;

}

public void run(){//

while (counter <= countTo) {

tc1_P.P();//tell thread 1 to sleep

TestClass1.print(counter);

counter = counter + 2;

tc2_V.V();//tell thread 2 to wake up

}

}

public static void print(int counter)

{

System.out.println(counter);

}

}

class TestClass2 implements Runnable{

int counter = 1;

int countTo;

Semaphore tc1_V;

Semaphore tc2_P;

TestClass2(int count, Semaphore tc1_V, Semaphore tc2_P)

{

this.countTo = count+1;

this.tc1_V = tc1_V;

this.tc2_P = tc2_P;

}

public void run(){//

while (counter < countTo)

{

tc2_P.P(); //tell thread 2 to sleep

TestClass1.print(counter);

counter = counter + 2;

tc1_V.V(); //tell thread 1 to wake up

}

}

}

file: Semaphore.java

public class Semaphore

{

int count;

Semaphore(int counter)

{

count = counter;

}

Semaphore()

{

count = 1;

}

public synchronized void P()

{

count--;

if (count < 0)

try

{

wait();

}

catch (Exception e)

{

System.out.println("Exception: " + e);

}

}

public synchronized void V()

{

count++;

if (count >= 0)

notify();

}

}

mmersic2 at 2007-6-29 9:12:07 > top of Java-index,Archived Forums,Java Programming...
# 9
Well, that certainly sheds a whole new light on things. Is it a real leap to add a third, fourth,... thread?
joseph_mueller at 2007-6-29 9:12:07 > top of Java-index,Archived Forums,Java Programming...
# 10

it should always be as easy to add a 3rd thread as a 99th thread. once you get the code, it does not matter how many you add.

Hes right about the order of execution. You will probably find that 1 thread runs many times, then the other on windows. But you cant guarantee that behavior.

dnoyeB at 2007-6-29 9:12:07 > top of Java-index,Archived Forums,Java Programming...
# 11
You can gaurentee order of execution, I just did, check the code above. The operating system the virtual machine is running in makes no difference here.-Mike
mmersic2 at 2007-6-29 9:12:07 > top of Java-index,Archived Forums,Java Programming...
# 12

When writting multithreaded java programs, it's a good practice to give CPU time for other threads to run, calling the yield() method (sleep(long) also works for it).

In your example, it should be:

void printOdds(){

//print ODD numbers up to 9

for(int index=1; index<=9; index+=2){

System.out.println(index);

Thread.currentThread().yield();

}

}

The importance of it depends on the priority of the concurrent threads and how the operating system treats them (preemptive or non-preemptive).

U063667 at 2007-6-29 9:12:07 > top of Java-index,Archived Forums,Java Programming...
# 13
Or, because yield() is a static method, you can simply callThread.yield();
schapel at 2007-6-29 9:12:07 > top of Java-index,Archived Forums,Java Programming...
# 14

> You can gaurentee order of execution, I just did,

> check the code above. The operating system the

> virtual machine is running in makes no difference

> here.

>

> -Mike

Well of course the JVM will do what you tell it. but the OS will switch threads as it sees fit, if your running on OS level threads. You cant stop that if you want to run efficiently. If you manually thread switch, you will be slowing your execution.

dnoyeB at 2007-6-29 9:12:07 > top of Java-index,Archived Forums,Java Programming...
# 15

> > You can gaurentee order of execution, I just did,

> > check the code above. The operating system the

> > virtual machine is running in makes no difference

> > here.

> >

> > -Mike

>

> Well of course the JVM will do what you tell it. but

> the OS will switch threads as it sees fit, if your

> running on OS level threads. You cant stop that if

> you want to run efficiently. If you manually thread

> switch, you will be slowing your execution.

>

Enough talk. Show me the code for a faster way to gaurentee the order of exection. (a little faster means nothing, you're talking alot of crap so I expect you to have an order of magnitude improvement up your sleave.)

-Mike

mmersic2 at 2007-7-1 1:42:10 > top of Java-index,Archived Forums,Java Programming...