Presentation is loading. Please wait.

Presentation is loading. Please wait.

MultiThreading Sangeetha Parthasarathy 07/10/2001.

Similar presentations


Presentation on theme: "MultiThreading Sangeetha Parthasarathy 07/10/2001."— Presentation transcript:

1 MultiThreading Sangeetha Parthasarathy 07/10/2001

2 What is multithreading? In the early days of computing, computers were single tasking--that is, they ran a single job at a time. The big, lumbering machine would start one job, run that job to completion, then start the next job, and so on. When engineers became overly frustrated with these batch-oriented systems, they rewrote the programs that ran the machines and thus was born the modern multitasking operating system.

3 Multitasking refers to a computer's capability to perform multiple jobs concurrently. For the most part, modern operating systems like Windows 95 or Solaris can run two or more programs at the same time. While you are using Netscape to download a big file, you can be running Solitaire in a different window; both programs are running at the same time. Multithreading is an extension of the multitasking paradigm. But rather than multiple programs, multithreading involves multiple threads of control within a single program. Not only is the operating system running multiple programs, each program can run multiple threads of control--think of threads as subprograms--within the program. For example, using a Web browser, you can print one Web page, download another, and fill out a form in a third--all at the same time.

4 What is a Java Thread? Java threads allow you to write programs that do many things at once. Each thread represents an independently executing sequence of control. One thread can write a file out to disk while a different thread responds to user keystroke events. One of the greatest benefits of Java is that it presents the Java programmer with a unified multithreading API--one that is supported by all Java virtual machines on all platforms. When you use Java threads, you do not have to worry about which threading packages are available on the underlying platform or whether the operating system supports kernel threads. The virtual machine isolates you from the platform-specific threading details. The Java threading API is identical on all Java implementations.

5 Creating New Threads This process of creating threads involves two steps: writing the code that is executed in the thread and writing the code that starts the thread. Threads aren't much use if you don't know how to create them. Fortunately, you have two options for creating and using threads in your own programs: Derive your class from the Thread class and override its run method. Implement the Runnable interface in your class and provide an implementation for the run method.

6 Both of these approaches revolve around providing a run method, which is where all the actual processing takes place. After a thread has been created and initialized, its run method is called and given the opportunity to perform whatever processing the thread is designed to provide. Because it provides all the processing power, the run method is the heart of a thread. It's not uncommon for the run method to consist of an infinite loop that performs some repetitive action like updating the frames of an animation.

7 Deriving from the Thread Class If your class isn't derived from a specific class, you can easily make it threaded by deriving it from the Thread class. The following source code shows how to add thread functionality to a class by deriving from the Thread class: public class ThreadMe extends Thread { public run() { // do some busy work } }

8 It's as easy as that! To use this class in a real program and set the thread in motion, you simply create a ThreadMe object and call the start method inherited from Thread, like this: ThreadMe me = new ThreadMe(); me.start(); The start method automatically calls run and gets the thread busy performing its processing. The thread will then run until the run method exits or the thread is stopped, suspended, or killed. If for some reason you want to stop the thread's execution, just call the stop method, like this: me.stop();

9 Implementing the Runnable Interface If your class needs to derive from a class other than Thread, you are forced to implement the Runnable interface to make it threaded. A very common situation where you have to do this is when an applet class needs to be threaded. Because applet classes must be derived from the Applet class, and Java doesn't provide a mechanism for multiple inheritance, you have no other option but to implement the Runnable interface to add threading support. You implement the Runnable interface in a class like this: public class ThreadYou implements Runnable { public run() { // do some busy work } }

10 As you can see, the only syntactic difference in this approach is that you use the implements keyword instead of extends. However, notice that you can still use the extends keyword to derive from another class, like this: public class ThreadedApp extends Applet implements Runnable { public run() { // do some busy work } } This is a very practical scenario involving an applet class with a run method that performs some type of threaded processing.

11 Even though the definition of a class implementing the Runnable interface is little different than directly deriving from Thread, there is a big difference when it comes to creating the thread and getting it running. Creating and running a threaded class implementing the Runnable interface is a three-part process, as the following code shows: ThreadYou you = new ThreadYou(); Thread t = new Thread(you); t.start(); Unlike the previous approach involving creating a thread object and calling its start method, this approach requires you to create both an instance of your class and a separate instance of the Thread class. You pass your object into the Thread class's constructor, which gives it access to your run method. You then set the thread running by calling the thread object's start method.

12 The thread in turn executes your object's run method. The thread knows your class has a run method because it implements the Runnable interface. If you have no need to access the thread after you get it started, the creation and starting of the thread can be combined into one statement, like this: ThreadYou you = new ThreadYou(); new Thread(you).start(); This approach eliminates the creation of the local variable t, which makes the code a little more efficient.

13 Scheduling and Thread Priority You may be wondering how any software system can be truly threaded when running on a machine with a single CPU. If there is only one physical CPU in a computer system, it's impossible for more than one machine code instruction to be executed at a time. This means that no matter how hard you try to rationalize the behavior of a multithreaded system, only one thread is really being executed at a particular time. The reality is that multithreading on a single CPU system, like the systems most of us use, is at best a good illusion. The good news is that the illusion works so well most of the time that we feel pretty comfortable in the thought that multiple threads are really running in parallel.

14 The illusion of parallel thread execution on a system with a single CPU is often managed by giving each thread an opportunity to execute a little bit of code at regular intervals. This approach is known as timeslicing, which refers to the way each thread gets a little of the CPU's time to execute code. When you speed up this whole scenario to millions of instructions per second, the whole effect of parallel execution comes across pretty well. The general task of managing and executing multiple threads in an environment such as this is known as scheduling. So far, I've described the most basic form of timesliced scheduling, where every thread is given equal access to the processor in small increments. In reality, this turns out not to be the best approach to managing thread execution. Undoubtedly, there are going to be situations where you would like some threads to get more of the CPU's attention

15 than others. To accommodate this reality, most threaded systems employ some type of prioritization to allow threads to execute at different priority levels. Java employs a type of scheduling known as fixed priority scheduling, which schedules thread execution based on the relative priorities between threads. It works like this: each thread is assigned a relative priority level, which determines the order in which it receives access to the CPU. High-priority threads are given first rights to the CPU, while low-priority threads are left to execute when the CPU is idle. One interesting thing about Java's approach to scheduling is that it doesn't employ timeslicing. In other words, the currently executing thread gets to enjoy the complete control of the CPU until it yields control to other threads. Lower- priority threads must simply wait until high-priority threads

16 give them a chance to execute. Threads with the same priority level are given access to the CPU one after the next. A good example of a low-priority thread is the garbage collection thread in the Java runtime system. Even though garbage collection is a very important function, it is not something you want hogging the CPU. Because the garbage collection thread is a low-priority thread, it chugs along in the background freeing up memory as the processor allows it. This may result in memory being freed a little more slowly, but it allows more time-critical threads, such as the user input handling thread, full access to the CPU.

17 Thread Priority When a new thread is created, it inherits its priority from the thread that created it. The Thread class defines three constants representing the relative priority levels for threads, which follow: MIN_PRIORITY NORM_PRIORITY MAX_PRIORITY The Java garbage collection thread has a priority of MIN_PRIORITY, whereas the system thread that manages user input events has a priority of MAX_PRIORITY. Knowing this, it's a good idea to take the middle road for most of your own threads and declare them as NORM_PRIORITY.

18 Generally speaking, this should happen without your having to do anything special because the parent thread you are creating threads from will likely be set to NORM_PRIORITY. If, however, you want to explicitly set a thread's priority, it's pretty easy-the Thread class provides a method called setPriority that allows you to directly set a thread's priority. The thread priority constants are actually integers that define a range of priorities. MIN_PRIORITY and MAX_PRIORITY are the lower and upper limits of the range of acceptable priority values, while NORM_PRIORITY rests squarely in the middle of the range. This means that you can offset these values to get varying priority levels.

19 Thread States A Java thread, represented by a Thread object, traverses a fixed set of states during its lifetime. When a Thread object is first created, it is in the NEW state. At this point, the thread is not executing. When you invoke the Thread's start() method, the thread changes to the RUNNABLE state. When a Java thread is RUNNABLE, it is eligible for execution. However, a thread that is RUNNABLE is not necessarily running. RUNNABLE implies that the thread is alive and that it can be allocated CPU time by the system when the CPU is available--but the CPU may not always be available.

20 On single-processor systems, Java threads must share the single CPU; additionally, the Java virtual machine task (or process) must also share the CPU with other tasks running on the system. When certain events happen to a RUNNABLE thread, the thread may enter the NOT RUNNABLE state. When a thread is NOT RUNNABLE, it is still alive, but it is not eligible for execution. The thread is not allocated time on the CPU. Some of the events that may cause a thread to become NOT RUNNABLE include the following: The thread is waiting for an I/O operation to complete The thread has been put to sleep for a certain period of time (using the sleep() method) The wait() method has been called (as discussed in "Synchronization," later in this chapter) The thread has been suspended (using the suspend() method)

21 A NOT RUNNABLE thread becomes RUNNABLE again when the condition that caused the thread to become NOT RUNNABLE ends (I/O has completed, the thread has ended its sleep() period, and so on). During the lifetime of a thread, the thread may frequently move between the RUNNABLE and NOT RUNNABLE states. When a thread terminates, it is said to be DEAD. Threads can become DEAD in a variety of ways. Usually, a thread dies when its run() method returns. A thread may also die when its stop() or destroy() method is called. A thread that is DEAD is permanently DEAD--there is no way to resurrect a DEAD.

22 Thread Class Constructors: The Thread class has seven different constructors: public Thread(); public Thread(Runnable target); public Thread(Runnable target, String name); public Thread(String name); public Thread(ThreadGroup group, Runnable target); public Thread(ThreadGroup group, Runnable target, String name); public Thread(ThreadGroup group, String name);

23 These constructors represent most of the combinations of three different parameters: thread name, thread group, and a Runnable target object. To understand the constructors, you must understand the three parameters: name is the (string) name to be assigned to the thread. If you fail to specify a name, the system generates a unique name of the form Thread-N, where N is a unique integer. target is the Runnable instance whose run() method is executed as the main method of the thread. group is the ThreadGroup to which this thread will be added. (The ThreadGroup class is discussed in detail later in this chapter.) Constructing a new thread does not begin the execution of that thread. To launch the Thread object, you must invoke its start() method.

24 Thread methods Naming: 1.public final String getName(); 2.public final void setName(String name); Every Java thread has a name. The name can be set during construction or with the setName() method. If you fail to specify a name during construction, the system generates a unique name of the form Thread-N, where N is a unique integer; the name can be changed later using setName(). The name of a thread can be retrieved using the getName() method.

25 Starting and Stopping To start and stop threads once you have created them, you need the following methods: 3.public void start(); 4.public final void stop(); 5.public final void stop(Throwable obj); 6.public void destroy(); To begin a new thread, create a new Thread object and call its start() method. An exception is thrown if start() is called more than once on the same thread.

26 Setting Thread Priority public final static int MAX_PRIORITY = 10; public final static int MIN_PRIORITY = 1; public final static int NORM_PRIORITY = 5; 7. public final int getPriority(); 8. public final void setPriority(int newPriority); Every thread has a priority. When a thread is created, it inherits the priority of the thread that created it. The priority can be adjusted subsequently using the setPriority() method. The priority of a thread can be obtained using getPriority(). There are three symbolic constants defined in the Thread class that represent the range of priority values: MIN_PRIORITY, NORM_PRIORITY, and MAX_PRIORITY. The priority values range from 1 to 10, in increasing priority.

27 Waking Up a Thread 9.public void interrupt(); 10.public static boolean interrupted(); 11.public boolean isInterrupted(); To send a wake-up message to a thread, call interrupt() on its Thread object. Calling interrupt() causes an InterruptedException to be thrown in the thread and sets a flag that can be checked by the running thread using the interrupted() or isInterrupted() method. Calling Thread.interrupted() checks the interrupt status of the current thread and resets the interrupt status to false.Calling isInterrupted() on a Thread object (which can be other than the current thread) checks the interrupt status of that thread but does not change the status. The interrupt() method is useful in waking a thread from a blocking operation such as I/O, wait(), or an attempt to enter a synchronized method.

28 Suspending and Resuming Thread Execution 12.public final void suspend(); 13.public final void resume(); Sometimes, it is necessary to pause a running thread. You can do so using the suspend() method. Calling the suspend() method ensures that a thread will not be run. The resume() method reverses the suspend() operation. A call to suspend() puts the thread in the NOT RUNNABLE state. However, calling resume() does not guarantee that the target thread will become RUNNABLE; other events may have caused the thread to be NOT RUNNABLE (or DEAD).

29 Putting a Thread to Sleep 14.public static void sleep(long millisecond); 15.public static void sleep(long millisecond, int nanosecond); To pause the current thread for a specified period of time, call one of the varieties of the sleep() method. For example, Thread.sleep(500) pauses the current thread for half a second, during which time the thread is in the NOT RUNNABLE state. When the specified time expires, the current thread again becomes RUNNABLE.

30 Making a Thread Yield 16.public static void yield(); The yield() method is used to give a hint to the thread scheduler that now would be a good time to run other threads. If many threads are RUNNABLE and waiting to execute, the yield() method is guaranteed to switch to a different RUNNABLE thread only if the other thread has at least as high a priority as the current thread.

31 Waiting for a Thread to End 17.public final void join(); 18.public final void join(long millisecond); public final void join(long millisecond, int nanosecond); Programs sometimes have to wait for a specific thread to terminate; this is referred to as joining the thread. To wait for a thread to terminate, invoke one of the join() methods on its Thread object.


Download ppt "MultiThreading Sangeetha Parthasarathy 07/10/2001."

Similar presentations


Ads by Google