In one word, we use Threads to make Java application faster by doing multiple things at same time. In technical terms, Thread helps you to achieve parallelism in Java program. Since CPU is very fast and nowadays it even contains multiple cores, just one thread is not able to take advantage of all the cores, which means your costly hardware will remain idle for most of the time. By using multiple threads, you can take full advantage of multiple cores by serving more clients and serving them faster. Since, in today's fast-paced world, response time matters a lot and that's why you have multi-core CPUs, but if your application doesn't make full use of all resources then there is no point adding them, multi-threading is one way to exploiting huge computing power of CPU in Java application.
There is one more purpose of using Thread in Java, to doing multiple tasks simultaneously. For example, in GUI application, you want to draw screens at the same time you also want to capture user's action e.g. pressing keys and command and you may want to download or uploading something from the network.
If you do all this task in one thread, they would be executed sequentially i.e. first you draw the screen then you capture the command and finally you upload your high score to the network. This may cause a problem for your game or application because GUI seems to be frozen while you doing another task. By using multiple threads in Java you can execute each of this task independently.
Reasons for using Multithreading in Java
Even Java application contains at least one thread, that is called main thread which executes your main method. There are more threads used by JVM e.g. daemon threads which do garbage collections and some other housekeeping works. As an application developer, you can also add new user threads to make your application faster and more efficient. Here are a couple of common reasons and scenarios to use multiple threads in Java:
1) To make a task run parallel to another task e.g. drawing and event handling.
GUI applications e.g. Swing and Java FX GUIs are the best examples of multi-threading in Java. In a typical GUI application, the user initiates an action e.g. downloading a file from network or loading games modules from hard disk. These actions require some time to complete but you cannot freeze the GUI because then the user will think your application is hung. Instead, you need a separate thread to carry out the time-consuming task and keep showing relevant messages to the user or allow him to do other tasks at the same time to keep your GUI alive. This is achieved by using multiple threads in Java.
2) To take full advantage of CPU power.
Another common reason for using multiple threads in Java is to improve throughput of the application by utilizing full CPU power. For example, if you have got 32 core CPU and you are only using 1 of them for serving 1000 clients and assuming that your application is CPU bound, you can improve throughput to 32 times by using 32 threads, which will utilize all 32 cores of your CPU. You can further read a good book on Java performance tuning books e.g. Java Performance The Definitive Guide By Scott Oaks to learn more about the performance impact of multi-threading.
3) For reducing response time
You can also use multiple threads to reduce response time by doing fast computation by dividing a big problem into smaller chunks and processing them by using multiple threads. For example, the map-reduce pattern is based upon dividing a big problem into smaller one and processing them individually, Java also provides Fork-Join Thread pool for just that purpose.
4) To sever multiple clients at the same time.
One of the most common scenarios where using multiple threads significantly improve an application's performance is a client-server application. A single threaded application means only one client can connect to the server at a time, but a multi-threaded server means multiple clients can connect to the server at same time. This means next client don't have to wait until your application finish processing request of the previous client.
Like in the following example, you can see that multiple requests are processing by our multi-threaded server at same time.
By the way, Threading is not free, it comes with its own challenges. You can only maximize throughput of your application up to certain extent, once numbering of the thread increases up to a certain threshold, they will start competing for CPU and context switching will occur. Context switching means one thread which is using CPU is suspended and CPU is allocated to another thread for execution. When this happens, thread generally loses all of their cached data. If that thread resumes on another core then it has to build its cache from the start.
Threading also introduces a special set of a problem known as multi-threading issue e.g. deadlock, livelock, memory inconsistency error, race conditions, and starvation. It's also very difficult to test a Java program which involves multiple threads. You cannot predict the order of execution in case of multi-threading and without any synchronization.
Also, parallelism will be limited to the fact of the size of critical section i.e. the part of the code which must be executed by the only thread at a time. If you have a long critical section then eventually all thread will wait there and your program will behave like a single threaded program.
That's all about why use Threads in Java. The fundamental of using a thread is same as using multiple workers to complete a task, but you must remember that not all task can be completed early by just deploying multiple workers e.g. 9 mothers cannot deliver a baby in one month. Similarly, just creating multiple threads to make your program faster will not work. You can only improve performance by dividing CPU bound task to multiple threads e.g. large computations. If your application is IO bound, then you may need to think about other techniques e.g. faster hard disk to improve performance.
You should also consider problems associated with multi-threading because handling synchronization between multiple threads and preventing issues like deadlock, livelock, starvation and memory inconsistency issues are not easy. Often a single thread is what you need because it makes coding easy, you don't need to synchronize anything if your application is single threaded.
No comments:
Post a Comment