Welcome to Workbook eleven point six, the main focus of this workbook is going to be thread safety
and locking critical parts of our code.
And so the first thing we're gonna do is define a function whose document I'm going to copy right now.
Copied over.
And the function seems to be void, so we'll say public static void.
It's called increments, and it expects a string parameter called file.
And now inside the function or in a run through every single line inside the file and from learning
the part, I left you a line of code to obtain the path.
We're going to have to make some imports.
And this throws an exception.
Uri syntax exceptions, so from here in a try to run the code.
And catch the exception if the cartels catch your eye syntax exception.
And print the message that the exception comes with in case of a failure.
Now we're going to use the file class to read every single line in the file path as a stream, so we'll
see files.
The lines will pass in the path.
And now we can run through every single line inside of whatever file we're passing in as a stream of
elements.
And so the first operation is to map every single element to a quantity value, but if you look at the
first row, it's just a bunch of column headers that we need to skip.
So the first operation actually has to be the skip the first line.
And then what we need to do is map every element to a quantity value.
So will map to ENT because quantity is an integer.
Here we receive every single element in the stream as a line string.
And here what we need to do is split the string around the comma separator, what that's going to do
is return an array of three string values.
We knew that Index two was an integer value.
So what we're going to do?
Is return index to and from the string value, we're going to say INT?
Or integer, I should say that percent.
Pass an integer out of the following string value.
OK, so at this point in the pipeline, every single element in the stream was mapped to a quantity.
And now we're going to run through every single quantity.
This is going to be our terminal operation.
This terminal operation in this case, returns void.
It's going to run through every single quantity and every time we run through an element inside the
stream, what we're going to do is increment the sample size.
So here we'll say sample size plus plus.
And quantity plus equals quantity.
Seems there's an exception we have to catch, and it is the i o exception catch.
I know exception.
And so now what we need to do is call this function first HSV one, two and three, so we're enough
to call this three different times.
We're going to assume this should run in the background because every year we file as about 500000 records.
So back here, what I'm going to do.
Is it going to create a threat pool?
Oh, you know what, we should probably highlight this and bring it back a little so you can press shift
and tab.
This should be good.
OK.
And now what I'm going to do is create a threat pool.
Secular service, secular.
And I don't know why the inventing is out, there should be at least four spaces one two three four.
OK is equal to executor's.
New fixed threat pool, and since we're just performing three tasks, we'll just have three threads.
And now what we can say is executor that submit.
And we're going to submit.
Oh, you know what, it seems like it's better to just run through this array of files.
So for.
I is smaller than files that length.
We're going to say executor.
Does submit here will call the runnable task increment.
And to it, we're going to pass and files an index I.
We seem to be getting an error, and you know what?
Instead of using a for loop that relies on a counter, we'll just use the for each loop.
We'll run through every single string inside of the files array.
And here we'll say executor does submit.
And submit our runnable task.
OK, and as we submit every single task, they're going to automatically run in the background and we
need to make sure that all tasks have been completed before we display the information to the user.
So what I'm going to do is create a countdown match countdown that's large is equal to a new countdown
clock.
That counts down from three.
And to our increment function.
I'm going to pass any latch.
And at the end of every task, we're going to say large dark countdown.
And then right here, if we say a large Typekit await.
This latch is going to stay closed until it counts down to zero, which in this case until every single
task has been executed.
And to right here we can safely present the data to the user.
You can say sample size.
And reference the sample size.
You can also say quantity sold.
In reference, the quantity sold.
If everything works correctly, we should be getting the following values.
I'll keep them to for now.
We'll run the application, oh, don't forget, actually shut down the executor service.
OK.
And this is not good.
Also, another thing quantity sold is zero.
That's oh the variable here should be quantity sold, not quantity.
That makes more sense.
We'll just rerun it.
Yeah, that's not good at all.
The correct values are the following, and you'd be wondering why the values aren't correct, and once
again, it's because of race conditions.
This part of the code is vulnerable to race conditions.
It should only be accessed and updated one thread at a time.
And so what we can do is employ a locking mechanism to ensure that this critical code is indeed accessed
one thread at a time.
So what we can do is create a re entrant like right here entrant lock, lock.
Is equal to a new object of the entrant lock class.
We can pass that log into our incremental function.
And whenever the runtime gets to hear whatever threat it may be, we need to make sure to lock this
part of the code so that it's only access to one thread at a time.
And after the following code has finished running on one thread, then we can unlock our reentry lock
so that another thread who is waiting to access this code can now run it.
OK, and if we run our code now.
We're going to have to pass our lock into here.
If we were in the code.
And these are the correct results.
Beautiful.