Sometimes we're facing the problem, that we need to solve using dynamic thread pool.
By 'dynamic' I mean, that the pool is shrinking and growing automatically but it does have upper bound (so it can't grow indefinitely).
The API of the pool would be quite simple:
We should be able to submit the task to be executed asynchronously and monitor number of threads in the pool.
Having control over maximum number of threads and their longevity would be another feature.
Let's try to document functional requirements in the form of unit tests.
That would be our test setup:
Initial number of threads should be zero:
The execution of the tasks should be done concurrently:
Number of threads should grow automatically:
The size of thread pool should shrink when there is no active tasks and keep alive time was exceeded:
If the number of submitted task is greater than maximum threads number, we should block:
Actual implementation is quite simple, we need to use ThreadPoolExecutor:
There are two important things here.
First, we are required to create our own RejectedExecutionHandler to support blocking when the maximum number is exceed.
Secondly, we need to use the blocking queue of size zero (in our case I chose SynchronousQueue) - the queue needs to be filled up before we can create more than initial number of threads (in our case zero).
The whole project can be found at github.
Monday, 6 July 2015
Sunday, 16 March 2014
Several approaches to processing events (part 2 - asynchronous processing with blocking queues and thread pool)
In the previous post we were solving problem with computing prime factors for numbers read from a large file.
We were taking a synchronous approach, which was quite easy to implement but very slow.
This time we'll try to go the asynchronous way using blocking queues and thread pool.
First of all, let's take a look at our Reader class:
The reader reads each line and puts it into the blocking queue. Once it's finished, it informs the latch.
The LineProcessor class is more complicated:
Let's take a closer look at the collaborators.
inputQueue is the queue that Reader is writing to.
successQueue and exceptionsQueue are the queues that will be populated based on the line processing result.
inputLatch is the latch modified by the Reader.
outputLatch will be informed when there are no more lines to be processed.
The LineProcessor checks if the Reader already finished by checking inputLatch and inputQueue.
If it didn't, it takes a line from the inputQueue and and populates appropriate queue with the result.
If it did finish, it informs outputLatch and terminates processing.
The Writer class is quite simple:
It takes the messages from the queue and writes it to a file.
It terminates, if the queue is empty and the latch was informed that there is no more messages.
The only thing left is the Bootstrap class that binds it all together:
The latches and queues are initialized and then passed to the processing objects via constructor.
Line processors are wrapped in a thread pool.
Reader and two writers are started as threads. We then wait until all writers are finished and the summary is printed.
We can check the behavior with the following test:
On a machine with Core2 Duo 2.53GHz it takes ~43 seconds to process 10 000 numbers.
The whole project can be found at github.
We were taking a synchronous approach, which was quite easy to implement but very slow.
This time we'll try to go the asynchronous way using blocking queues and thread pool.
First of all, let's take a look at our Reader class:
The reader reads each line and puts it into the blocking queue. Once it's finished, it informs the latch.
The LineProcessor class is more complicated:
Let's take a closer look at the collaborators.
inputQueue is the queue that Reader is writing to.
successQueue and exceptionsQueue are the queues that will be populated based on the line processing result.
inputLatch is the latch modified by the Reader.
outputLatch will be informed when there are no more lines to be processed.
The LineProcessor checks if the Reader already finished by checking inputLatch and inputQueue.
If it didn't, it takes a line from the inputQueue and and populates appropriate queue with the result.
If it did finish, it informs outputLatch and terminates processing.
The Writer class is quite simple:
It takes the messages from the queue and writes it to a file.
It terminates, if the queue is empty and the latch was informed that there is no more messages.
The only thing left is the Bootstrap class that binds it all together:
The latches and queues are initialized and then passed to the processing objects via constructor.
Line processors are wrapped in a thread pool.
Reader and two writers are started as threads. We then wait until all writers are finished and the summary is printed.
We can check the behavior with the following test:
On a machine with Core2 Duo 2.53GHz it takes ~43 seconds to process 10 000 numbers.
The whole project can be found at github.
Wednesday, 26 February 2014
Scheduling tasks with Spring (updated)
Spring provides an easy way to schedule tasks.
Let's say that we would like to have an information about current time printed on a console periodically.
The class that prints the time may look like this:
We need to define a class that will encapsulate the printing task:
The @Scheduled annotation is the key here: the method reportCurrentTime is annotated by it, therefore it will be invoked every 5 seconds.
You can also specify cron expression. You can use fixedRateString parameter if you want to read it from properties file.
Please note setting of the thread name - it will be needed for the test.
Adding production code only for tests is generally not a good practice, but in this case it can also be used for monitoring purposes.
The spring configuration looks as following:
To run it we need to create an invoker class:
Unfortunately there is no trivial way to test it automatically. We can do it the following way.
Let's create a test class:
When we run the test, the spring context will start and the task will be invoked by scheduler.
We check if the thread with our name exists.
We do it for some time to avoid race condition - it may happen that verification method will be invoked before thread starts.
The whole project alongside with dependencies can be found on github.
Let's say that we would like to have an information about current time printed on a console periodically.
The class that prints the time may look like this:
We need to define a class that will encapsulate the printing task:
The @Scheduled annotation is the key here: the method reportCurrentTime is annotated by it, therefore it will be invoked every 5 seconds.
You can also specify cron expression. You can use fixedRateString parameter if you want to read it from properties file.
Please note setting of the thread name - it will be needed for the test.
Adding production code only for tests is generally not a good practice, but in this case it can also be used for monitoring purposes.
The spring configuration looks as following:
To run it we need to create an invoker class:
Unfortunately there is no trivial way to test it automatically. We can do it the following way.
Let's create a test class:
When we run the test, the spring context will start and the task will be invoked by scheduler.
We check if the thread with our name exists.
We do it for some time to avoid race condition - it may happen that verification method will be invoked before thread starts.
The whole project alongside with dependencies can be found on github.
Monday, 13 January 2014
Several approaches to processing events (part 1 - synchronous processing)
Let's consider the following problem that we have to solve:
We have a file with numbers (each line has one number).
Our goal is to process every number and count its prime factors.
We need to write the result along with the processed number in a separate file.
In case of any exception during processing we need to write the exception to a file together with the number that was processed by the time it occurred.
Apart from that we also need to write the summary of the time that we spent on processing.
The class that counts prime factors looks as following:
The simplest but not the optimal way to solve this would be to process each line synchronously. It could look like that:
We're reading lines from numbers.txt file and then we're processing each line in a for loop. At the end we're writing everything to three files.
The Reader and Writer classes are quite simple:
They're using Guava and Apache Commons dependencies that have following declaration:
We can check the results in a following test:
On a machine with Core2 Duo 2.53GHz it takes ~73 seconds to process 10 000 numbers.
The whole project can be found at github.
In next posts we'll take a look at other approaches to solve this problem.
We have a file with numbers (each line has one number).
Our goal is to process every number and count its prime factors.
We need to write the result along with the processed number in a separate file.
In case of any exception during processing we need to write the exception to a file together with the number that was processed by the time it occurred.
Apart from that we also need to write the summary of the time that we spent on processing.
The class that counts prime factors looks as following:
The simplest but not the optimal way to solve this would be to process each line synchronously. It could look like that:
We're reading lines from numbers.txt file and then we're processing each line in a for loop. At the end we're writing everything to three files.
The Reader and Writer classes are quite simple:
They're using Guava and Apache Commons dependencies that have following declaration:
We can check the results in a following test:
On a machine with Core2 Duo 2.53GHz it takes ~73 seconds to process 10 000 numbers.
The whole project can be found at github.
In next posts we'll take a look at other approaches to solve this problem.
Sunday, 27 October 2013
Running Hadoop locally without installation
If we want to take Hadoop for a test-drive without installing the whole distribution, we can do it quite easily.
First of all, let's create a maven project with the following dependencies:
There is a known issue with running newer version on Windows, so the older one is chosen.
Cygwin is also required to be installed when running on Windows.
We will create a job to count the words in files (it's a well-known example taken from the official tutorial).
Our mapper would look like:
The mapper splits the lines from file into words and pass on each word as the key with the value of one.
Here comes the reducer:
The reducer receives all values for given key and counts them.
All that is left is a main class that will run the job:
We are setting job's mapper, reducer and classer for key and value.
Input and output paths are set as well.
You can run it directly and check the output file with the result.
The whole project can be found on github.
First of all, let's create a maven project with the following dependencies:
There is a known issue with running newer version on Windows, so the older one is chosen.
Cygwin is also required to be installed when running on Windows.
We will create a job to count the words in files (it's a well-known example taken from the official tutorial).
Our mapper would look like:
The mapper splits the lines from file into words and pass on each word as the key with the value of one.
Here comes the reducer:
The reducer receives all values for given key and counts them.
All that is left is a main class that will run the job:
We are setting job's mapper, reducer and classer for key and value.
Input and output paths are set as well.
You can run it directly and check the output file with the result.
The whole project can be found on github.
Saturday, 21 September 2013
Transaction management with Spring Data JPA
Spring provides an easy way to manage transactions.
Let's see how to make our methods transactional without using any XML configuration.
We will start with Spring Java config for our application:
We have an entity representing a bank account:
We also have a repository from Spring Data JPA for Account objects:
The TransferService allows transferring money from one account to another:
Just for example sake, we are adding money to one account and before subtracting from the second one, we check if it has enough funds.
If the method wasn't transactional, we would introduce a major bug.
However, @Transactional annotation makes it eligible for rollback if the exception is thrown.
It's also important to note that many methods from the repository are transactional with default propagation, so the transaction from our service will be reused.
Let's make sure that it works by writing an integration test:
If we remove @Transactional annotation the test will fail.
Be aware that managing transactions with Spring have some traps that are described in this article.
The whole project can be found at github.
Let's see how to make our methods transactional without using any XML configuration.
We will start with Spring Java config for our application:
We have an entity representing a bank account:
We also have a repository from Spring Data JPA for Account objects:
The TransferService allows transferring money from one account to another:
Just for example sake, we are adding money to one account and before subtracting from the second one, we check if it has enough funds.
If the method wasn't transactional, we would introduce a major bug.
However, @Transactional annotation makes it eligible for rollback if the exception is thrown.
It's also important to note that many methods from the repository are transactional with default propagation, so the transaction from our service will be reused.
Let's make sure that it works by writing an integration test:
If we remove @Transactional annotation the test will fail.
Be aware that managing transactions with Spring have some traps that are described in this article.
The whole project can be found at github.
Thursday, 29 August 2013
Changing application behavior at runtime with JMX
Sometimes we need to be able to change the behavior of our application without a restart.
JMX, apart from its monitoring capabilities, is a perfect solution for this.
Spring provides great JMX that will ease our task.
Let's start with a simple service, which behavior we will change at runtime.
DiscountService calculates discount based on a globalDiscount - it's value is harcoded for simplicity purposes, it would probably be read from some configuration file or database in more realistic example.
First of all, in order to expose methods to manage globalDiscount we need to add @ManagedResource annotation to our class and add the methods with @ManagedOperation annotation.
We could also use @ManagedAttribute if we would treat these methods as simple getter and setter for globalDiscount.
Class with needed methods and annotations would look like:
In Spring configuration we just need to define the bean for DiscountService and enabling exporting MBeans with MBean server.
We can run the application with:
Now we're ready to manage our service with jconsole:
Our service is exposed locally, but if we want to be able to connect to it remotely, we will need to add following beans to the Spring configuration:
Service is now exposed via RMI.
We can invoke the exposed methods programmatically, which allows us to write some scripts and manage services without using jconsole.
Let's write an integration test to check that it works correctly.
We will need a Spring config for the test with the RMI client.
The test will increment the value of globalDiscount.
Take a closer look at exposed methods invocation, which is very cumbersome, especially if the method has parameters.
The whole project can be found at github.
JMX, apart from its monitoring capabilities, is a perfect solution for this.
Spring provides great JMX that will ease our task.
Let's start with a simple service, which behavior we will change at runtime.
DiscountService calculates discount based on a globalDiscount - it's value is harcoded for simplicity purposes, it would probably be read from some configuration file or database in more realistic example.
First of all, in order to expose methods to manage globalDiscount we need to add @ManagedResource annotation to our class and add the methods with @ManagedOperation annotation.
We could also use @ManagedAttribute if we would treat these methods as simple getter and setter for globalDiscount.
Class with needed methods and annotations would look like:
In Spring configuration we just need to define the bean for DiscountService and enabling exporting MBeans with MBean server.
We can run the application with:
Now we're ready to manage our service with jconsole:
Our service is exposed locally, but if we want to be able to connect to it remotely, we will need to add following beans to the Spring configuration:
Service is now exposed via RMI.
We can invoke the exposed methods programmatically, which allows us to write some scripts and manage services without using jconsole.
Let's write an integration test to check that it works correctly.
We will need a Spring config for the test with the RMI client.
The test will increment the value of globalDiscount.
Take a closer look at exposed methods invocation, which is very cumbersome, especially if the method has parameters.
The whole project can be found at github.
Subscribe to:
Posts (Atom)
