Movatterモバイル変換


[0]ホーム

URL:


Jump to content
WikibooksThe Free Textbook Project
Search

Threads and Runnables

75% developed
From Wikibooks, open books for an open world
<Java Programming
Thelatest reviewed version waschecked on16 April 2020. There aretemplate/file changes awaiting review.

Concurrent ProgrammingJava Programming
Threads and Runnables
Basic Synchronization
NavigateConcurrent Programming topic:()


CPUs for any computer are designed to execute one task atany given time, yet we run multiple applications side-by-side and everything works in perfect congruence. It's not just because CPUs are extremely fast in performing calculations, it's because CPUs use a clever device of dividing their time amongst various tasks. Each application or task that is invoked on a computer gets associated with the CPU in the form of aprocess. A CPU therefore manages various processes, and jumps back and forth amongst each process giving it a fraction of its time and processing capability. This happens so fast that to a normal computer user it presents with the illusion of processes being run simultaneously. This capability of the CPU to divide its time amongst processes is calledmultitasking.

So, if we run a Java application on a computer, we are effectively creating a process with the CPU that gets a fraction of the CPU's time. In Java parlance, this main process gets called thedaemon process or thedaemon thread. But, Java goes one step further. It allows programmers to divide this daemon thread into several multiple threads which get executed simultaneously (much like a CPU) hence providing a Java application with a finer multitasking capability calledmultithreading.

In this section, we will take a look at what threads are and how multithreading is implemented within a Java program to make it appear congruent and effectively fast to respond.

Threads

[edit |edit source]

In light of the above discussion, a thread is the smallest unit of processing that can be scheduled by an operating system. Therefore, using threads, a programmer can effectively create two or more tasks[1] that run at the same time. The first call-to-action is to implement a set of tasks that a particular thread would execute. To do so, we require the creation of aRunnable process.

Creating a Runnable process block

[edit |edit source]

ARunnable process block is a simple class that implements arun() method. Within therun() method is the actual task that needs to be executed by a running thread. By implementing a class with theRunnable interface, we ensure that the class holds arun() method. Consider the following program:

Computer codeCode listing 1: A runnable process
importjava.util.Random;publicclassRunnableProcessimplementsRunnable{privateStringname;privateinttime;privateRandomrand=newRandom();publicRunnableProcess(Stringname){this.name=name;this.time=rand.nextInt(999);}publicvoidrun(){try{System.out.printf("%s is sleeping for %d \n",this.name,this.time);Thread.sleep(this.time);System.out.printf("%s is done.\n",this.name);}catch(Exceptionex){ex.printStackTrace();}}}

In the above code, we create a class calledRunnableProcess and implement theRunnable interface to ensure that we have arun() method in the class declaration.

ExampleCode section 1.1: Implementing theRunnable interface
publicclassRunnableProcessimplementsRunnable{...publicvoidrun(){...}}

We then declare the rest of the logic for the class. For the constructor, we take aString parameter that would serve as the name of the class. Then, we initialize the class member variabletime with a random number between0 and999. To ensure the initialization of a random number, we use theRandom class in thejava.util package.

ExampleCode section 1.2: Including ability to generate random integers between0 and999
importjava.util.Random;...privateRandomrand=newRandom();...this.time=rand.nextInt(999);

The actual task that would be executed per this runnable block is presented within therun() method. To keep safe from exceptions occurring because of the concurrent programming, we wrap the code within this method with atry..catch block. The executing task actually consists of just three statements. The first outputs the provided name for the Runnable process, and the last reports that the thread has executed. Perhaps the most intriguing part of the code is the second statement:Thread.sleep(...).

ExampleCode section 1.3: The actual runnable process task
...System.out.printf("%s is sleeping for %d \n",this.name,this.time);Thread.sleep(this.time);System.out.printf("%s is done \n",this.name);...

This statement allows the thread executing the current runnable block to halt its execution for the given amount of time. This time is presented in milliseconds. But for our convenience, this time would be the random number generated in the constructor and can be anywhere between0 and999 milliseconds. We will explore this in a later section. Creating aRunnable process block is just the beginning. No code is actually executed. To do so, we would require the creation of threads that would then individually execute this task.

Creating threads

[edit |edit source]

Once we have aRunnable process block, we can create various threads that can then execute the logic encased within such blocks. Multithreading capabilities in Java are utilized and manipulated using theThread class. AThread object therefore holds all the necessary logic and devices to create truly multithreaded programs. Consider the following program:

Computer codeCode listing 2: CreatingThread objects
publicclassThreadLogic{publicstaticvoidmain(String[]args){Threadt1=newThread(newRunnableProcess("Thread-1"));Threadt2=newThread(newRunnableProcess("Thread-2"));Threadt3=newThread(newRunnableProcess("Thread-3"));}}

Creating threads is as simple as the above program suggests. You just have to create an object of theThread class and pass a reference to aRunnable process object. In the case above, we present theThread constructor with the class object for theRunnableProcess class that we created incode listing 1. But for each object, we give a different name (i.e.,"Thread-1" and"Thread-2", etc.) to differentiate between the threeThread objects. The above example only declaresThread objects and hasn't yet started them for execution.

Starting threads

[edit |edit source]

Now, that we know how to effectively create aRunnable process block and aThread object that executes it, we need to understand how to start the createdThread objects. This couldn't be simpler. For this process, we will be calling thestart() method on theThread objects and voilà, our threads will begin executing their individual process tasks.

Computer codeCode listing 3: Starting theThread objects
publicclassThreadLogic{publicstaticvoidmain(String[]args){Threadt1=newThread(newRunnableProcess("Thread-1"));Threadt2=newThread(newRunnableProcess("Thread-2"));Threadt3=newThread(newRunnableProcess("Thread-3"));t1.start();t2.start();t3.start();}}

The above code will start all three declared threads. This way, all three threads will begin their execution one-by-one. However, this being concurrent programming and us having declared random times for the halting of the execution, the outputs for every one of us would differ. Following is the output we received when we executed the above program.

Computer codeOutput forcode listing 3
Thread-1 is sleeping for 419Thread-3 is sleeping for 876Thread-2 is sleeping for 189Thread-2 is doneThread-1 is doneThread-3 is done

It should be noted that the execution of theThread didn't occur in the desired order. Instead of the ordert1t2t3, the threads executed in the order oft1t3t2. The order in which the threads are executed is completely dependent on the operating system and may change for every execution of the program, thus making output of multithreaded application difficult to predict and control. Some people suggest that this is the major reason that adds to the complexity of multithreaded programming and its debugging. However, it should be observed that once the threads were put to sleep using theThread.sleep(...) function, the execution intervals and order can be predicted quite capably. The thread with the least amount of sleeping time wast2 ("Thread-2") with189 milliseconds of sleep hence it got called first. Thent1 was called and finallyt3 was called.

Manipulating threads

[edit |edit source]

It can be said that the execution order of the threads was manipulated to some degree using theThread.sleep(...) method. TheThread class has such static methods that can arguably affect the execution order and manipulation of threads. Below are some useful static methods in theThread class. These methods when called will only affect the currently running threads.

MethodDescription
Thread.currentThread()Returns the currently executing thread at any given time.
Thread.dumpStack()Prints a stack trace of the currently running thread.
Thread.sleep(long millis)Halts execution of the currently running thread for the given amount of time (in milliseconds).
throwsInterruptedException
Thread.sleep(long millis, int nanos)Halts execution of the currently running thread for the given amount of time (in milliseconds plus provided nanoseconds).
throwsInterruptedException
Thread.yield()Temporarily pauses the execution of the currently running thread to allow other threads to execute.

Synchronization

[edit |edit source]
The text in its current form is incomplete.

Given below is an example of creating and running multiple threads that behave in a synchronous manner such that when one thread is using a particular resource, the others wait until the resource has been released. We will talk more about this in later sections.

Computer codeCode listing 4: Creation of the multipleThread objects running synchronously
publicclassMultiThreadExample{publicstaticbooleancthread;publicstaticStringstuff=" printing material";publicstaticvoidmain(Stringargs[]){Threadt1=newThread(newRunnableProcess());Threadt2=newThread(newRunnableProcess());t1.setName("Thread-1");t2.setName("Thread-2");t2.start();t1.start();}/*     * Prints information about the current thread and the index it is     * on within the RunnableProcess     */publicstaticvoidprintFor(intindex){StringBuffersb=newStringBuffer();sb.append(Thread.currentThread().getName()).append(stuff);sb.append(" for the ").append(index).append(" time.");System.out.print(sb.toString());}}classRunnableProcessimplementsRunnable{publicvoidrun(){for(inti=0;i<10;i++){synchronized(MultiThreadExample.stuff){MultiThreadExample.printFor(i);try{MultiThreadExample.stuff.notifyAll();MultiThreadExample.stuff.wait();}catch(InterruptedExceptionex){ex.printStackTrace();}}}}}
Computer codeOutput forcode listing 4
Thread-1 printing material for the 0 time.Thread-2 printing material for the 0 time.Thread-1 printing material for the 1 time.Thread-2 printing material for the 1 time.Thread-1 printing material for the 2 time.Thread-2 printing material for the 2 time.Thread-1 printing material for the 3 time.Thread-2 printing material for the 3 time.Thread-1 printing material for the 4 time.Thread-2 printing material for the 4 time.Thread-1 printing material for the 5 time.Thread-2 printing material for the 5 time.Thread-1 printing material for the 6 time.Thread-2 printing material for the 6 time.Thread-1 printing material for the 7 time.Thread-2 printing material for the 7 time.Thread-1 printing material for the 8 time.Thread-2 printing material for the 8 time.Thread-1 printing material for the 9 time.Thread-2 printing material for the 9 time.

Where are threads used?

[edit |edit source]
Video games intensively use threads

Threads are used intensively in applications that require a considerable amount of CPU usage. For operations that are time-consuming and intensive, it is usually advised to use threads. An example of such an application would be a typical video game. At any given time, a video game involves various characters, objects in the surroundings and other such nuances that needs to be dealt with simultaneously. Dealing with each element or object within the game requires a fair amount of threads to monitor every object.

For example, take this screen-shot of a role-playing strategy game on the right. Here the game visuals depict various in-game characters moving about on the screen. Now imagine processing the movements, direction and behaviors of each of the characters visible on screen. It would certainly take a lot of time moving each character one-by-one if this were to be done one task after another. However if fundamentals of multi-threading are employed, each character would move in a synchronous manner with respect to others.

Threads are not only used heavily in video games, their use is common in everything from simple browser applications to complex operating systems and networking applications. Today it often goes beyond the simple preference of the developer but into the need to maximize the usefulness of contemporaneous hardware that is predicated in heavy multitasking.

References

[edit |edit source]
  1. The number of tasks that can be run simultaneously for a single Java application depends on how many tasks an operating system allows to be multithreaded.

Daemon thread tutorial


Clipboard

To do:
Add some exercises like the ones inVariables


Concurrent ProgrammingJava Programming
Threads and Runnables
Basic Synchronization
Retrieved from "https://en.wikibooks.org/w/index.php?title=Java_Programming/Threads_and_Runnables&oldid=3675797"
Category:
Hidden categories:

[8]ページ先頭

©2009-2025 Movatter.jp