Hi! Today we'll continue to talk about multithreading. Let's examine the Thread class and what a few of its methods do. When we studied class methods previously, we usually just wrote this: <method name> -> <what the method does>.
This won't work with
Thread
's methods :) They have more complex logic that you won't be able to figure out without a few examples.
The Thread.start() method
Let's start by repeating ourselves. As you probably recall, you can create a thread by making your class inherit theThread
class and overriding the run()
method.
But it won't start itself, of course. To do this, we call our object's start()
method.
Let's recall the example from the previous lesson:
Note: To start a thread, you must call the special start()
method rather than the run()
method! This is an easy error to make, especially when you first start studying multithreading.
In our example, if you call the run()
method 10 times instead of start()
, you would get this:
Look at the results of our program:
Thread executed: Thread-0
Thread executed: Thread-1
Thread executed: Thread-2
Thread executed: Thread-3
Thread executed: Thread-4
Thread executed: Thread-5
Thread executed: Thread-6
Thread executed: Thread-7
Thread executed: Thread-8
Thread executed: Thread-9
Look at the order of the output: Everything is happening in perfect order. Weird, huh? We're not used to this, because we already know that the order in which threads are started and executed is determined by a superior intellect inside our operating system: the thread scheduler. Maybe we just got lucky?
Of course, this isn't about luck. You can verify this by running the program a couple more times.
The issue is that call the run()
method directly has nothing to do with multithreading. In this case, the program will be executed on the main thread, the same thread that executes the main()
method. It simply successively print 10 lines on the console and that's it. 10 threads haven't been started.
So, remember this in the future and constantly check yourself. If you want the run()
method to be called, call start()
. Let's go further.
The Thread.sleep() method
To suspend execution of the current thread for a while, we use thesleep()
method.
The sleep()
method takes a number of milliseconds as an argument, which indicates the amount of time to put the thread to sleep.
Console output:
- How long did I sleep?
- 3 seconds
Note: the sleep()
method is static: it sleeps the current thread.
That is, the one currently being executed. Here's another important point: a sleeping thread can be interrupted. In this case, the program throws an InterruptedException
. We'll consider an example below.
By the way, what happens after the thread wakes up? Will it continue to be executed right from where it left off? No. After a thread wakes up, i.e. the time passed as an argument to Thread.sleep()
has passed, it transitions into runnable state. But, this doesn't mean that the thread scheduler will run it. It may quite possibly give preference to some other non-sleeping thread and allow our freshly-awakened thread to continue its work a little later.
Be sure to remember this: waking up doesn't mean continuing work immediately!
The Thread.join() method
Thejoin()
method suspends execution of the current thread until another thread finishes.
If we have 2 threads, t1
and t2
, and we write
then t2
won't start until t1
has finished its work. The join()
method can be used to guarantee the execution order of threads.
Let's consider how the join()
method works in the following example:
We created a simple ThreadExample
class. Its task is to display a message that the thread has started, fall asleep for 5 seconds, and then finally report that the work is complete.
Piece of cake. The main logic is in the Main
class. Look at the comments: we use the join()
method to successfully manage the threads' execution order. If you remember how we started this topic, execution order is handled by the thread scheduler. It runs threads at its own discretion: each time in a different way.
Here we are using the method to guarantee that the t1
thread will first be started and executed first, then the t2
thread, and only after that will the program's main thread continue.
Moving on.
In real programs, you'll often find situations when you will need to interrupt the execution of a thread. For example, our thread is running, but it's waiting for a certain event or condition. If it occurs, then the thread stops. It would probably make sense if there was some sort of stop()
method.
But it's not so simple. Once upon a time, Java actually did have a Thread.stop()
method and allowed a thread to be interrupted. But it was later removed from the Java library. You can find it in the Oracle documentation and see that it is marked as deprecated.
Why? Because it just stopped the thread without doing anything else.
For example, the thread might be working with data and changing something. Then in the middle of its work it was abruptly and unceremoniously cut off by the stop()
method. Without a proper shutdown, nor the release of resources, not even error handling — there was none of this.
To exaggerate slightly, the stop()
method simply destroyed everything in its way.
It was like pulling the power cord from the outlet to turn off the computer. Yeah, you can get the desired result. But everybody knows that after a couple of weeks the computer won't be thanking you for treating it that way.
That's why the logic for interrupting threads changed in Java and now uses a special interrupt()
method.
The Thread.interrupt() method
What happens if theinterrupt()
method is called on a thread?
There are 2 possibilities:
- If the object was in the waiting state, for example, due to the
join
orsleep
methods, then the wait will be interrupted and the program will throw anInterruptedException
. - If the thread was in a functioning state, then the boolean
interrupted
flag will be set on the object.
Thread
class has the boolean isInterrupted()
method.
Let's return to the clock example that was in a lesson in the basic course. For convenience, we've simplified it slightly:
In this case, the clock is started and starts ticking every second. In the 10th second, we interrupt the clock's thread.
As you already know, if the thread that we're trying to interrupt is in one of the waiting states, the result is an InterruptedException
. This is a checked exception, so we can be easily catch it and execute our logic to finish the program. And that's just what we did.
Here's our result:
Tick
Tick
Tick
Tcik
Tick
Tick
Tick
Tick
Tick
The thread was interrupted
This concludes our introduction to the Thread
class's most important methods.
Good luck!
No comments:
Post a Comment
Note: Only a member of this blog may post a comment.