Showing posts with label threads. Show all posts
Showing posts with label threads. Show all posts

Wednesday, June 15, 2011

Chapter 1: Introduction to Threads

Threads are an important and interesting aspect of the Java Programming Language. If you are an experienced Java Programmer, you are invariably expected to know the intricacies of multi-threading. Well, this series of chapters is aimed at helping you understand this interesting and complicated concept.

So, lets get started!!!

Why Use Threads?

The notion of threading is so ingrained in Java that it's almost impossible to write even the simplest programs in Java without creating and using threads. And many of the classes in the Java API are already threaded, so often you are using multiple threads without realizing it.

The biggest question you might have is “Why use Threads?”

Well, my friend, it is not so simple to explain the reason in a couple of lines. Maybe a 100 page thesis would sound more appropriate. But still, am gonna try explaining in a short and concise manner.

First and foremost – threads increase performance. Given the processing power of the modern day processors, irrespective of how much code you write, the processor is going to finish running them in a jiffy and will remain underutilized almost 99% or more times. By creating multiple threads in your program, you are trying to utilize the processor effectively trying to keep it as little time as possible “idle”

Some of the significant reasons for using Threads are explained in the subsequent sections of this article.

Nonblocking I/O

In Java, as in most programming languages, when you try to get input from the user, you execute a read() method specifying the user's terminal (System.in in Java). When the program executes the read() method, the program typically waits until the user types at least one character before it continues and executes the next statement. This type of I/O is called blocking I/O : the program blocks until some data is available to satisfy the read() method.

This type of behavior is often undesirable. If you're reading data from a network socket, that data is often not available when you want to read it: the data may have been delayed in transit over the network, or you may be reading from a network server that sends data only periodically. If the program blocks when it tries to read from the socket, it's unable to do anything else until the data is actually available. If the program has a user interface that contains a button and the user presses the button while the program is executing the read() method, nothing happens: the program is unable to handle the mouse events and execute the event processing method associated with the button. This can be very frustrating for the user, who thinks the program has hung.

This kind of situation is where Threads in Java look the most promising solution.

Independent Tasks

A Java program is often called on to perform independent tasks. In the simplest case, a single applet may perform two independent animations for a web page. A more complex program would be a calculation server that performs calculations on behalf of several clients simultaneously. In either case, while it is possible to write a single-threaded program to perform multiple tasks, it's easier and more elegant to place each task in its own thread.

Parallelizable Algorithms

With the advent of virtual machines that can use multiple CPUs simultaneously, Java has become a useful platform for developing programs that use algorithms that can be parallelized; that is, running one iteration of the loop on one CPU while another iteration of the loop is simultaneously running on another CPU. Dependencies between the data that each iteration of the loop needs may prohibit a particular loop from being parallelized, and there may be other reasons why a loop should not be parallelized. But for many programs with CPU-intensive loops, parallelizing the loop greatly speeds up the execution of the program when it is run on a machine with multiple processors.

Now that we know why and how threads are useful for us as programmers, lets dig deep into the magical world of Threads!!!

Next: What is a Thread

Saturday, February 26, 2011

Quick Review: Chapters 55 to 61 (Threads)

This is going to be the last quick recap chapter in this SCJP Series. This will cover the important points about Threads.

Defining, Instantiating, and Starting Threads

* Threads can be created by extending Thread and overriding the public void run() method.

* Thread objects can also be created by calling the Thread constructor that takes a Runnable argument. The Runnable object is said to be the target of the thread.

* You can call start() on a Thread object only once. If start() is called more than once on a Thread object, it will throw a RuntimeException.

* It is legal to create many Thread objects using the same Runnable object as the target.

* When a Thread object is created, it does not become a thread of execution until its start() method is invoked. When a Thread object exists but hasn’t been started, it is in the new state and is not considered alive.

Transitioning Between Thread States

* Once a new thread is started, it will always enter the runnable state.

* The thread scheduler can move a thread back and forth between the runnable state and the running state.

* For a typical single-processor machine, only one thread can be running at a time, although many threads may be in the runnable state.

* There is no guarantee that the order in which threads were started determines the order in which they’ll run.

* There’s no guarantee that threads will take turns in any fair way. It’s up to the thread scheduler, as determined by the particular virtual machine implementation. If you want a guarantee that your threads will take turns regardless of the underlying JVM, you can use the sleep() method. This prevents one thread from hogging the running process while another thread starves.

* A running thread may enter a blocked/waiting state by a wait(), sleep(), or join() call.

* A running thread may enter a blocked/waiting state because it can’t acquire the lock for a synchronized block of code.

* When the sleep or wait is over, or an object’s lock becomes available, the thread can only reenter the runnable state. It will go directly from waiting to running (well, for all practical purposes anyway).

* A dead thread cannot be started again.

Sleep, Yield, and Join

* Sleeping is used to delay execution for a period of time, and no locks are released when a thread goes to sleep.

* A sleeping thread is guaranteed to sleep for at least the time specified in the argument to the sleep() method (unless it’s interrupted), but there is no guarantee as to when the newly awakened thread will actually return to running.

* The sleep() method is a static method that sleeps the currently executing thread’s state. One thread cannot tell another thread to sleep.

* The setPriority() method is used on Thread objects to give threads a priority of between 1 (low) and 10 (high), although priorities are not guaranteed, and not all JVMs recognize 10 distinct priority levels—some levels may be treated as effectively equal.

* If not explicitly set, a thread’s priority will have the same priority as the priority of the thread that created it.

* The yield() method may cause a running thread to back out if there are runnable threads of the same priority. There is no guarantee that this will happen, and there is no guarantee that when the thread backs out there will be a different thread selected to run. A thread might yield and then immediately reenter the running state.

* The closest thing to a guarantee is that at any given time, when a thread is running it will usually not have a lower priority than any thread in the runnable state. If a low-priority thread is running when a high-priority thread enters runnable, the JVM will usually preempt the running low-priority thread and put the high-priority thread in.

* When one thread calls the join() method of another thread, the currently running thread will wait until the thread it joins with has completed. Think of the join() method as saying, “Hey thread, I want to join on to your end. Let me know when you’re done, so I can enter the runnable state.”

Synchronization

* synchronized methods prevent more than one thread from accessing an object’s critical method code simultaneously.

* You can use the synchronized keyword as a method modifier, or to start a synchronized block of code.

* To synchronize a block of code, you must specify an argument that is the object whose lock you want to synchronize on.

* While only one thread can be accessing synchronized code of a particular instance, multiple threads can still access the same object’s unsynchronized code.

* When a thread goes to sleep, its locks will be unavailable to other threads.

* static methods can be synchronized, using the lock from the java.lang.Class instance representing that class.

Thread Communication

* The wait() method lets a thread say, “I got nothing to do, so put me in your waiting pool and notify me when something happens that I care about.”

* The notify() method is used to send a signal to one and only one of the threads that are waiting in that same object’s waiting pool.

* The notify() method can NOT specify which waiting thread to notify.

* The method notifyAll() works in the same way as notify(), only it sends the signal to all of the threads waiting on the object.

* All three methods—wait(), notify(), and notifyAll()—must be called from within a synchronized context! A thread invokes wait() or notify() on a particular object, and the thread must currently hold the lock on that object.

Deadlocks

* Deadlocking is when thread execution grinds to a halt because the code is waiting for locks to be removed from objects.

* Deadlocking can occur when a locked object attempts to access another locked object that is trying to access the first locked object. In other words, both threads are waiting for each other’s locks to be released; therefore, the locks will never be released!


Previous Chapter: Chapter 61 - Thread Interaction

Next Chapter: Self Test - Chapters 55 to 61

Friday, February 25, 2011

Chapter 56: Threads and Multithreading

This chapter and the subsequent ones on Threads and Multi-threading is probably by far the most complex topic we will be covering as part of our aim at getting a SCJP Certification.
Before we begin – let me put out a Disclaimer…

Disclaimer: This chapter makes almost no attempt to teach you how to design a good, safe, multithreaded application. The concepts covered in this article are just the tip of the iceberg and you’re here only to learn the basics of threading, and what you need to get through the thread questions on the exam. Before you can write decent multithreaded code, however, you really need to study more on the complexities and subtleties of multithreaded code.

In a single-threaded runtime environment, actions execute one after another. The next action can happen only when the previous one is finished. If task A takes half an hour, and the user wants to do something else, he is doomed to wait until task A is over.

Ideally, the user should be able to carry on with his other task until his first task is complete. Imagine having to wait till your eclipse build all your source code before you could check your email? Thankfully windows uses multiple threads to run your eclipse and outlook. So you don't have to go through this pain. Similarly java has options wherein the programmer can have multiple threads of execution running.

Now you are ready to dive into the magical or rather complicated world of threads.

Lets get started!!!

What is a Thread?

In Java, “thread” means:
• A thread of execution

A thread of execution is an individual process that has its own call stack. In Java, there is one thread per call stack or, to think of it in reverse, one call stack per thread. Even if you don’t create any new threads in your program, threads are there running without your knowledge.
If you are curious and ask me how? Just stop for a moment and think how you would execute a java program? You’ll write a main method and then execute it from the command line using the “java” command. Well, you have already answered the question because, when your main method starts, the JVM assigns a thread for this main method and assigns it a call stack. So, eventhough you did not intentionally create a thread, the system did one for you.

The most important concept to understand from this entire chapter is this:

When it comes to threads, very little is guaranteed.

So be very cautious about interpreting the behavior you see on one machine as “the way threads work.” The exam expects you to know what is and is not guaranteed behavior, so that you can design your program in such a way that it will work regardless of the underlying JVM.

Exam Tip:
The thread questions are among the most difficult questions on the exam. In fact, for most people they are the toughest questions on the exam. If you’re not already familiar with threads, you’ll probably need to spend some time experimenting.
Exam Tip:
The topic of daemon threads is NOT on the exam. All of the threads discussed in this chapter are “user” created threads. We can create a second kind of thread called a daemon thread. The difference between these two types of threads (user and daemon) is that the JVM exits an application only when all user threads are complete—the JVM doesn’t care about letting daemon threads complete, so once all user threads are complete, the JVM will shut down, regardless of the state of any daemon threads. Once again, this topic is NOT on the exam and it is enough if you know this much about daemon threads for the exam.

Creating a Thread

A thread in Java begins as an instance of java.lang.Thread. You’ll find methods in the Thread class for managing threads including creating, starting, and pausing them. They are:
start()
yield()
sleep()
run()

All the awesome action happens in the run() method. Think of the code you want to execute in a separate thread as the job to do. Lets say, you have some work that needs to be done, in the background while other things are happening in the program, so what you really want is that work to be executed in its own thread. All that code you want executed in a separate thread goes into the run() method.

Ex:
public void run() {
// your job code goes here
}

The run() method will call other methods, of course, but the thread of execution—the new call stack—always begins by invoking run(). So where does the run() method go? In one of the two classes you can use to define your thread job.

You can define and instantiate a thread in one of two ways:
• Extend the java.lang.Thread class.
• Implement the Runnable interface.

You need to know about both for the exam, although I would personally recommend that you implement Runnable than extend Thread. Extending the Thread class is the easiest, but it’s usually not a good OO practice.

Now, you may ask me “Why? Why should I choose the Runnable over Thread?”
Well, if you thought of the why before reading the preceding line, give yourself a pat on the back. Well done!

Because, if you extend the Thread class what would you do if you have to extend another concrete parent class that has vital/important behavior that you need in your class? Get the point? Java does not support direct multiple inheritance and hence, once you extend the Thread class, you are done, for good. You cannot extend any other class. That is why I recommended the Runnable interface. Even if you implement the interface, you are free to extend any class you want. Convenient, right?

Defining a Thread

To define a thread, you need a place to put your run() method, and as we just discussed, you can do that by extending the Thread class or by implementing the Runnable interface. We’ll look at both in this section.

Extending java.lang.Thread
The simplest way to define code to run in a separate thread is to
• Extend the java.lang.Thread class.
• Override the run() method.
It looks like this:
class MyFirstThread extends Thread {
public void run() {
System.out.println("Important job running in MyFirstThread");
}
}
The limitation with this approach is that if you extend Thread, you can’t extend anything else. And it’s not as if you really need that inherited Thread class behavior, because in order to use a thread you’ll need to instantiate one anyway.

Keep in mind that you’re free to overload the run() method in your Thread subclass:
class MyFirstThread extends Thread {
public void run() {
System.out.println("Important job running in MyFirstThread");
}
public void run(String s) {
System.out.println("String running is " + s);
}
}

Note: The overloaded run(String s) method will be ignored by the Thread class unless you call it yourself. The Thread class expects a run() method with no arguments, and it will execute this method for you in a separate call stack after the thread has been started. With a run(String s) method, the Thread class won’t call the method for you, and even if you call the method directly yourself, execution won’t happen in a new thread of execution with a separate call stack. It will just happen in the same call stack as the code that you made the call from, just like any other normal method call.


Implementing java.lang.Runnable

Implementing the Runnable interface gives you a way to extend any class you like, but still define behavior that will be run by a separate thread. It looks like this:

class MyFirstRunnableClass implements Runnable {
public void run() {
System.out.println("Imp job running in MyFirstRunnableClass");
}
}
Regardless of which mechanism you choose, you’ve now got yourself some code that can be run by a thread of execution. So now let’s take a look at instantiating your thread-capable class, and then we’ll figure out how to actually get the thing running.

Instantiating a Thread

Remember, every thread of execution begins as an instance of class Thread. Regardless of whether your run() method is in a Thread subclass or a Runnable implementation class, you still need a Thread object to do the work.

If you extended the Thread class, instantiation is dead simple:
MyFirstThread t = new MyFirstThread()

If you implement Runnable, instantiation is only slightly less simple. To have code run by a separate thread, you still need a Thread instance. But rather than combining both the thread and the run() method into one class, you’ve split it into two classes—the Thread class for the thread-specific code and your Runnable implementation class for your job-that-should-be-run-by-a-thread code.

First, you instantiate your Runnable class:
MyFirstRunnableClass r = new MyFirstRunnableClass();

Next, you get yourself an instance of java.lang. Thread, and you give it your job!
Thread t = new Thread(r); // Pass your Runnable to the Thread

If you create a thread using the no-arg constructor, the thread will call its own run() method when it’s time to start working. That’s exactly what you want when you extend Thread, but when you use Runnable, you need to tell the new thread to use your run() method rather than its own. The Runnable you pass to the Thread constructor is called the target or the target Runnable.
You can pass a single Runnable instance to multiple Thread objects, so that the same Runnable becomes the target of multiple threads, as follows:

public class TestMyThreads {
public static void main (String [] args) {
MyFirstRunnableClass r = new MyFirstRunnableClass();
Thread aaa = new Thread(r);
Thread bbb = new Thread(r);
Thread ccc = new Thread(r);
}
}

Giving the same target to multiple threads means that several threads of execution will be running the very same job and that same job will be done multiple times.

Exam Tip:
The Thread class itself implements Runnable. (After all, it has a run() method that we were overriding.) This means that you could pass a Thread to another Thread’s constructor:
Thread t = new Thread(new MyFirstThread());

This is a bit silly, but it’s legal. In this case, you really just need a Runnnable, and creating a whole other Thread is overkill.

Besides the no-arg constructor and the constructor that takes a Runnable (the target, i.e., the instance with the job to do), there are other overloaded constructors in class Thread. The constructors we care about are
• Thread()
• Thread(Runnable target)
• Thread(Runnable target, String name)
• Thread(String name)

You need to recognize all of them for the exam! Don't worry, we’ll discuss some of the other constructors in the preceding list a little later.

So now you’ve made yourself a Thread instance, and it knows which run() method to call. But nothing is happening yet. At this point, all we’ve got is a Java object of type Thread. It is not yet a thread of execution. To get an actual thread and a new call stack—we still have to start the thread.

When a thread has been instantiated but not started (in other words, the start() method has not been invoked on the Thread instance), the thread is said to be in the new state. At this stage, the thread is not yet considered to be alive. Once the start() method is called, the thread is considered to be alive (even though the run() method may not have actually started executing yet). A thread is considered dead (no longer alive) after the run() method completes. The isAlive() method is the best way to determine if a thread has been started but has not yet completed its run() method.

Note: The getState() method is very useful for debugging, but you won’t get any questions about it in the exam.

Starting a Thread

You’ve created a Thread object and it knows its target. Now it’s time to get the whole thread thing running. It’s pretty straight forward:
t.start();

Prior to calling start() on a Thread instance, the thread (when we use lowercase t, we’re referring to the thread of execution rather than the Thread class) is said to be in the new state as we said. The new state means you have a Thread object but you don’t yet have a true thread. So what happens after you call start()?

• A new thread of execution starts (with a new call stack).
• The thread moves from the new state to the runnable state.
• When the thread gets a chance to execute, its target run() method will run.

Be sure you remember the following: You start a Thread, not a Runnable. You call start() on a Thread instance, not on a Runnable instance. The following example demonstrates what we’ve covered so far—defining, instantiating, and starting a thread:



class TestRunnable implements Runnable {

public void run() {

for(int x = 1; x < 6; x++) {
System.out.println("Runnable running");

}

}

}



public class TestMyThreads {

public static void main (String [] args) {

TestRunnable r = new TestRunnable();

Thread t = new Thread(r);

t.start();

}

}



Running the preceding code prints out exactly what you’d expect:

% java TestMyThreads

Runnable running

Runnable running

Runnable running

Runnable running

Runnable running


Exam Tip: There’s nothing special about the run() method as far as Java is concerned. Like main(), it just happens to be the name (and signature) of the method that the new thread knows to invoke. So if you see code that calls the run() method on a Runnable (or even on a Thread instance), that’s perfectly legal. But it doesn’t mean the run() method will run in a separate thread! Calling a run() method directly just means you’re invoking a method from whatever thread is currently executing, and the run() method goes onto the current call stack rather than at the beginning of a new call stack. The following code does not start a new thread of execution:
Thread t = new Thread();
t.run();
The run method will be executed but there will be no new Thread.

So what happens if we start multiple threads? We’ll run a simple example in a moment, but first we need to know how to print out which thread is executing. We can use the getName() method of class Thread, and have each Runnable print out the name of the thread executing that Runnable object’s run() method. The following example instantiates a thread and gives it a name, and then the name is printed out from the run() method:

class TestRunnableWithNames implements Runnable {
public void run() {
System.out.println("TestRunnableWithNames running");
System.out.println("Run by "
+ Thread.currentThread().getName());
}
}
public class NameThread {
public static void main (String [] args) {
TestRunnableWithNames nr = new TestRunnableWithNames();
Thread t = new Thread(nr);
t.setName("Rocky");
t.start();
}
}

Running this code produces the following, extra special, output:

% java NameThread
TestRunnableWithNames running
Run by Rocky

To get the name of a thread you call getName() on the Thread instance. But the target Runnable instance doesn’t even have a reference to the Thread instance, so we first invoked the static Thread.currentThread() method, which returns a reference to the currently executing thread, and then we invoked getName() on that returned reference.

Even if you don’t explicitly name a thread, it still has a name. Let’s look at the previous code, commenting out the statement that sets the thread’s name:

public class NameThread {
public static void main (String [] args) {
TestRunnableWithNames nr = new TestRunnableWithNames();
Thread t = new Thread(nr);
// t.setName("Rocky");
t.start();
}
}
Running the preceding code now gives us
% java NameThread
TestRunnableWithNames running
Run by Thread-0

And since we’re getting the name of the current thread by using the static Thread.currentThread() method, we can even get the name of the thread running our main code,
public class NameThreadTwo {
public static void main (String [] args) {
System.out.println("thread is "
+ Thread.currentThread().getName());
}
}

which prints out
% java NameThreadTwo
thread is main

That’s right, the main thread already has a name—main.


Starting and Running Multiple Threads


Let’s actually get down to business and get multiple threads going (more than two, that is). We already had two threads, because the main() method starts in a thread of its own, and then t.start() started a second thread. Now we’ll do more. The following code creates a single Runnable instance and three Thread instances. All three Thread instances get the same Runnable instance, and each thread is given a unique name. Finally, all three threads are started by invoking start() on the Thread instances.



class TestRunnableWithNames implements Runnable {

public void run() {

for (int x = 1; x <= 3; x++) {
System.out.println("Run by "

+ Thread.currentThread().getName()

+ ", x is " + x);

}

}

}

public class ManyNames {

public static void main(String [] args) {

// Make one Runnable

TestRunnableWithNames nr = new TestRunnableWithNames();

Thread one = new Thread(nr);

Thread two = new Thread(nr);

Thread three = new Thread(nr);



one.setName("Rocky");

two.setName("Cena");

three.setName("Triple H");

one.start();

two.start();

three.start();

}

}

Running this code might produce the following:



% java ManyNames

Run by Rocky, x is 1

Run by Triple H, x is 1

Run by Rocky, x is 2

Run by Cena, x is 1

Run by Rocky, x is 3

Run by Cena, x is 2

Run by Cena, x is 3

Run by Triple H, x is 2

Run by Triple H, x is 3



Well, at least that’s what it printed when we ran it—this time, on our machine. But the behavior you see above is not guaranteed. I repeat, “THE BEHAVIOR IS NOT GUARANTEED.” You need to know, for your future as a Java programmer as well as for the exam, that there is nothing in the Java specification that says threads will start running in the order in which they were started (in other words, the order in which start() was invoked on each thread). And there is no guarantee that once a thread starts executing, it will keep executing until it’s done. Or that a loop will complete before another thread begins. Nothing is guaranteed in the preceding code except this:


Each thread will start, and each thread will run to completion.


Within each thread, things will happen in a predictable order. But the actions of different threads can mix together in unpredictable ways. If you run the program multiple times, or on multiple machines, you may see different output. Even if you don’t see different output, you need to realize that the behavior you see is not guaranteed. Sometimes a little change in the way the program is run will cause a difference to emerge. Just for fun we bumped up the loop code so that each run() method ran the for loop 400 times rather than 3, and eventually we did start to see some wobbling:




public void run() {

for (int x = 1; x <= 400; x++) {
System.out.println("Run by "

+ Thread.currentThread().getName()

+ ", x is " + x);

}

}



Running the preceding code, with each thread executing its run loop 400 times, started out fine but then became nonlinear. Here’s just a snip from the command-line output of running that code:

Run by Rocky, x is 345

Run by Triple H, x is 313

Run by Cena, x is 341

Run by Triple H, x is 314

Run by Cena, x is 342

Run by Triple H, x is 315

Run by Rocky, x is 346

Run by Cena, x is 343

Run by Rocky, x is 347

Run by Cena, x is 344

And so on…


Notice that there’s not really any clear pattern here. If we look at only the output from Rocky, we see the numbers increasing one at a time, as expected:

Run by Rocky, x is 345

Run by Rocky, x is 346

Run by Rocky, x is 347



And similarly if we look only at the output from Cena, or Triple H. Each one individually is behaving in a nice orderly manner. But together, it is utter chaos! In the fragment above we see Rocky, then Cena, then Triple H (in the same order we originally started the threads), but then Cena moves in when it was Rocky’s turn. And then Triple H and Cena trade back and forth for a while until finally Rocky gets another chance. They jump around like this for a while after this. Eventually (after the part shown above) Rocky finishes, then Triple H, and finally Cena finishes with a long sequence of output. So even though Triple H was started third, he actually completed second. And if we run it again, we’ll get a different result.


Why?


Because it’s up to the scheduler, and we don’t control the scheduler! Which brings up another key point to remember: Just because a series of threads are started in a particular order doesn’t mean they’ll run in that order. For any group of started threads, order is not guaranteed by the scheduler. And duration is not guaranteed. You don’t know, for example, if one thread will run to completion before the others have a chance to get in or whether they’ll all take turns nicely, or whether they’ll do a combination of both.


A thread is no longer a thread when its run() method completes execution.


When a thread completes its run() method, the thread ceases to be a thread of execution. The stack for that thread dissolves, and the thread is considered dead. Not dead and gone, but, just dead. It’s still a Thread object, just not a thread of execution. So if you’ve got a reference to a Thread instance, then even when that Thread instance is no longer a thread of execution, you can still call methods on the Thread instance, just like any other Java object. What you can’t do, though, is call start() again.


Once a thread has been started, it can never be started again.


If you have a reference to a Thread, and you call start(), it’s started. If you call start() a second time, it will cause an exception (an IllegalThreadStateException, which is a kind of RuntimeException, but you don’t need to worry about catching it). This happens whether or not the run() method has completed from the first start() call. Only a new thread can be started, and then only once. A runnable thread or a dead thread cannot be restarted.



Exam Tip: In addition to using setName() and getName to identify threads, you might see getld(). The getld() method returns a positive, unique, long number, and that number will be that thread’s only ID number for the thread’s entire life

The Thread Scheduler

The thread scheduler is the part of the JVM that decides which thread should run at any given moment, and also takes threads out of the run state. Assuming a single processor machine, only one thread can actually run at a time. Only one stack can ever be executing at one time. And it’s the thread scheduler that decides which thread among all other eligible threads will actually run. When I say eligible, it means threads that are in the runnable state.

Any thread in the runnable state can be chosen by the scheduler to be the one and only running thread. If a thread is not in a runnable state, then it cannot be chosen to be the currently running thread. And, to repeat something I have already said:

THE ORDER IN WHICH RUNNABLE THREADS ARE CHOSEN TO RUN IS NOT AND I MEAN IS NOT GUARANTEED!


Although we don’t control the thread scheduler, we can sometimes influence it. The following methods give us some tools for influencing the scheduler. Just don’t ever mistake influence for control.

Exam Tip: Expect to see exam questions that look for your understanding of what is and is not guaranteed! You must be able to look at thread code and determine whether the output is guaranteed to run in a particular way or is indeterminate

Methods from the java.lang.thread Class

Some of the methods that can help us influence thread scheduling are as follows:
public static void sleep(long millis) throws InterruptedException
public static void yield()
public final void join() throws InterruptedException
public final void setPriority(int newPriority)

Note that both sleep() and join() have overloaded versions which not shown here.

Methods from the java.lang.object Class

Every class in Java inherits the following three thread-related methods:
public final void wait() throws InterruptedException
public final void notify()
public final void notifyAll()

The wait() method has three overloaded versions (including the one listed here).

Don't worry too much about the functionalities of these methods because we are going to have a full chapter dedicated to these babies.

For now, the chapter is over. You can give a sigh of relief which is exactly what I am doing now.. Huh!!!

Previous Chapter: Self Test - Chapters 52 to 55

Next Chapter: Thread States & Transition
© 2013 by www.inheritingjava.blogspot.com. All rights reserved. No part of this blog or its contents may be reproduced or transmitted in any form or by any means, electronic, mechanical, photocopying, recording, or otherwise, without prior written permission of the Author.

ShareThis

Google+ Followers

Followers