1 00:00:00,060 --> 00:00:03,030 Thread Pool can reuse threads to run new tasks. 2 00:00:06,180 --> 00:00:09,090 In this lesson, you're going to use a thread pool to run your tasks. 3 00:00:12,240 --> 00:00:17,310 Creating a threat is pretty slow, and you should avoid the habit of always creating a new threat whenever 4 00:00:17,310 --> 00:00:18,240 there's a new task. 5 00:00:20,880 --> 00:00:26,190 Let's remove the target variable and define a target array. 6 00:00:27,370 --> 00:00:29,800 Targets with three values. 7 00:00:31,590 --> 00:00:35,850 Well, say point five point eight point three. 8 00:00:37,890 --> 00:00:43,420 So as you can probably guess, our application has to generate three guesses and really important. 9 00:00:43,440 --> 00:00:50,460 Let's reduce the precision by two decimal places to shorten the execution time because what if it just 10 00:00:50,460 --> 00:00:52,520 has a really hard time guessing one of the numbers? 11 00:00:52,530 --> 00:00:53,920 We don't want it to take forever. 12 00:00:54,300 --> 00:00:57,930 This amount of decimal places is accurate enough. 13 00:00:59,650 --> 00:01:03,550 And since we're going to be repeating a lot of the same code, let's just shorten it. 14 00:01:04,000 --> 00:01:07,990 For instance, we can just define the callable directly inside the future task. 15 00:01:09,780 --> 00:01:10,180 OK. 16 00:01:11,010 --> 00:01:16,800 And now our difference function is going to expect another parameter, that parameter is INT index. 17 00:01:18,260 --> 00:01:22,430 And we're going to evaluate the difference between the target at index. 18 00:01:23,770 --> 00:01:26,290 Against the number that was generated by the application. 19 00:01:28,990 --> 00:01:32,620 Generate number is also going to receive an index and index. 20 00:01:43,710 --> 00:01:49,860 And given what we know so far, your first instinct would be to create a new thread for each new task, 21 00:01:49,860 --> 00:01:53,970 which, by the way, isn't the best practice, but for now we'll just do it anyway. 22 00:01:54,780 --> 00:01:58,080 I will copy and paste this two more times. 23 00:01:59,970 --> 00:02:05,250 Here, the task will generate a number that is accurate to the first target. 24 00:02:05,880 --> 00:02:09,660 This one is going to do the same thing for the second target and third. 25 00:02:11,100 --> 00:02:14,430 We'll call this future to feature three. 26 00:02:16,920 --> 00:02:19,980 We'll call this thread three and thread for. 27 00:02:24,840 --> 00:02:25,150 OK. 28 00:02:25,170 --> 00:02:29,880 After creating the threads, we can start them right away, or we can say thread three dots starts. 29 00:02:31,140 --> 00:02:33,120 Thread for Dodd starts. 30 00:02:34,700 --> 00:02:39,720 OK, this is already looking not the best, but anyways, I'm going to change my print statements here 31 00:02:39,720 --> 00:02:50,040 to, uh, forget the returned values for now, we'll just say finished running background operations. 32 00:02:55,200 --> 00:02:57,660 And now how can we make sure that we'll delete this for now? 33 00:02:58,800 --> 00:03:02,940 And now, how can we make sure that every single thread has finished running by the time we get to this 34 00:03:02,940 --> 00:03:03,270 line? 35 00:03:04,110 --> 00:03:09,720 Remember that future dog get wait until a thread is finished executing its task, and it's going to 36 00:03:09,720 --> 00:03:12,510 get the final value that the callable is holding onto? 37 00:03:13,290 --> 00:03:15,870 So what we will have to do is forget this. 38 00:03:16,060 --> 00:03:18,450 We'll just say FutureGen two more times. 39 00:03:22,190 --> 00:03:23,690 OK, and now if you run the code. 40 00:03:27,270 --> 00:03:32,160 You know what, the term of this, I think you get the point by now, it's not blocking the main thread. 41 00:03:39,380 --> 00:03:44,930 And for the number of decimal places that we specified, this performed relatively well, not the best. 42 00:03:45,620 --> 00:03:52,310 Now the take home message is that after a thread finishes running, it dies and then you have to create 43 00:03:52,310 --> 00:03:54,170 a new threat once that thread dies. 44 00:03:54,470 --> 00:03:58,220 Say you have another task, then you have to create another threat and another. 45 00:04:03,130 --> 00:04:06,700 Now, let's imagine I wanted to run generate number a few hundred times. 46 00:04:07,090 --> 00:04:08,980 Would you expect to create 100 threads? 47 00:04:09,530 --> 00:04:10,660 Uh, probably not. 48 00:04:10,660 --> 00:04:11,200 A good idea. 49 00:04:11,440 --> 00:04:17,230 That would be incredibly taxing because for each thread that you create, there are so many slow operations 50 00:04:17,230 --> 00:04:18,730 that the JVM needs to perform. 51 00:04:19,149 --> 00:04:22,120 So you might think, OK, yeah, I'm creating so many threads. 52 00:04:22,330 --> 00:04:25,210 So many of my tasks are being performed at the same time. 53 00:04:25,570 --> 00:04:30,520 But there is actually a trade off when you create too many threads because they consume a lot of resources. 54 00:04:30,760 --> 00:04:36,160 There are so many slow operations that the JVM needs to perform for each thread, and it's actually 55 00:04:36,160 --> 00:04:37,750 going to make your application slower. 56 00:04:38,470 --> 00:04:40,630 So the point is we can use a thread pool. 57 00:04:47,020 --> 00:04:52,330 Imagine we have a fixed thread pool with three threads every time we submit a task to the thread pool. 58 00:04:52,570 --> 00:04:54,940 It's going to use one of its threads to perform the task. 59 00:04:55,240 --> 00:04:57,010 In this case, we submitted three tasks. 60 00:05:02,830 --> 00:05:06,850 And after every thread performs its task, the thread stays active, it doesn't die. 61 00:05:08,870 --> 00:05:11,550 Let's just imagine we have another task to thread pool. 62 00:05:11,750 --> 00:05:14,600 It's going to reuse one of the threads to perform the task. 63 00:05:18,290 --> 00:05:24,800 So right here, what we're going to do is create a fixed thread pool with three threads executor service. 64 00:05:25,900 --> 00:05:27,490 Well, just call it executor. 65 00:05:28,930 --> 00:05:36,220 Is equal to from the executors, we're going to create a new fixed threat pool that has three threads. 66 00:05:37,210 --> 00:05:42,580 And then what I can do is just directly submit every single callable to the thread pool. 67 00:05:43,100 --> 00:05:50,560 Oh, if you look here, actually, you can see that the submit method is overloaded to accept a runnable 68 00:05:50,560 --> 00:05:52,420 task or a callable task. 69 00:05:52,750 --> 00:05:54,550 We're going to submit a callable task. 70 00:05:55,860 --> 00:05:57,150 Or three, for that matter? 71 00:06:00,910 --> 00:06:02,110 One and two. 72 00:06:05,320 --> 00:06:08,140 And already this is looking a lot cleaner. 73 00:06:09,540 --> 00:06:15,690 And what's beautiful about this is as soon as you submit a task, it already starts running in the background, 74 00:06:15,960 --> 00:06:18,510 so we don't need to say that the red dots start or anything. 75 00:06:19,290 --> 00:06:24,930 When you submit a callable, however, it returns a future object that we can use to extract the return 76 00:06:24,930 --> 00:06:26,610 value after the threat is finished. 77 00:06:27,030 --> 00:06:28,440 So here I can say future. 78 00:06:30,390 --> 00:06:30,900 Double. 79 00:06:35,140 --> 00:06:38,020 Future is equal to executor, does submits. 80 00:06:39,420 --> 00:06:40,590 Can do the same thing here. 81 00:06:41,780 --> 00:06:42,230 And here. 82 00:06:46,940 --> 00:06:47,380 OK. 83 00:06:47,510 --> 00:06:49,130 And if we run the app now. 84 00:06:52,400 --> 00:06:55,430 Everything still works, and you'll notice the app doesn't shut down. 85 00:06:56,090 --> 00:06:59,870 Hope you understand why we created a threat pool with a size of three. 86 00:07:00,020 --> 00:07:02,750 And it's likely that each thread executes one task. 87 00:07:11,150 --> 00:07:15,800 After all, the tasks are complete, the threads haven't died, they're still active. 88 00:07:16,160 --> 00:07:21,500 So at the end, once every thread is finished, we need to make sure we shut down the executor service. 89 00:07:23,100 --> 00:07:24,960 Executor, Dutch shutdown. 90 00:07:32,600 --> 00:07:38,990 What's beautiful about this is I can even submit to other tasks and still only have three threads. 91 00:07:41,470 --> 00:07:46,270 The thread pool is just going to reuse two of its threads to perform the remaining tasks. 92 00:07:47,750 --> 00:07:48,680 Running that. 93 00:07:51,230 --> 00:07:52,550 And it finishes fairly quickly. 94 00:07:52,580 --> 00:07:58,010 Now keep in mind that the task scheduler is really a random concurrent execution is unpredictable in 95 00:07:58,010 --> 00:08:02,870 itself, so if for some reason it ends up being a bit too slow for you, feel free to increase it to 96 00:08:02,870 --> 00:08:05,690 four threads, or you can even reduce the precision. 97 00:08:06,170 --> 00:08:07,550 But in any case? 98 00:08:11,330 --> 00:08:12,920 Things are working out pretty well. 99 00:08:14,270 --> 00:08:19,970 Now you might be asking what is the ideal thread, pool size when you're performing CPU bound tasks, 100 00:08:20,240 --> 00:08:24,260 so tasks whose speed of execution depends on the speed of the CPU? 101 00:08:24,530 --> 00:08:28,760 Then a good rule of thumb is to set the number of threads equal to the number, of course, that your 102 00:08:28,760 --> 00:08:30,080 application has access to. 103 00:08:35,840 --> 00:08:41,210 And inside each other, you can obtain the number of cards your app has access to by using the following 104 00:08:41,210 --> 00:08:41,570 code. 105 00:08:42,169 --> 00:08:43,850 First, we're going to get the runtime. 106 00:08:44,660 --> 00:08:48,290 And how many processors are available to the applications runtime? 107 00:08:49,040 --> 00:08:50,450 I should get eight. 108 00:08:51,230 --> 00:08:54,410 You should get a different number because we're not using the same computer. 109 00:09:01,730 --> 00:09:05,040 Now, I'm just going to use this as my number of threats. 110 00:09:05,070 --> 00:09:10,830 You know what we'll say it's for clarity and numb threads is equal to runtime. 111 00:09:13,220 --> 00:09:13,910 All right. 112 00:09:23,980 --> 00:09:25,020 This works out pretty well. 113 00:09:26,850 --> 00:09:29,280 A threat pool retains an active number of threats. 114 00:09:29,580 --> 00:09:33,630 The rule of thumb is favor reusing threads over creating new ones. 115 00:09:34,110 --> 00:09:35,940 In other words, use a thread pool.