Exercise Notes

Learning goals

  • Software design approaches and patterns, to identify reusable solutions to commonly occurring problems
  • Apply an appropriate software development approach according to the relevant paradigm (for example object oriented, event driven or procedural)

Programs used

Part 1 – Threads

  1. Do a simple http GET to a website of your choice. You can copy/paste code from steps 3 and 9 (but not steps 4-8!) of https://www.baeldung.com/java-http-request to do this. This is only a preliminary step so if you have any difficulties then let your trainer know.
  2. Put your code into a method with the following signature. The method should return the web page as a string.
private static String getWebpage(String url)
  1. Create a Runnable which calls getWebpage on a web page of your choice and outputs the web page to System.out. Run your code in the following order:
    • Create the Runnable
    • Start the thread
    • Output “Thread has been started”
  2. You should see “Thread has been started” printed first, then the output of the thread afterwards even though you ran the code to print the web page first.
  3. After you’ve output that the thread has been started, called thread.join() to wait for the thread to finish. Then output “Thread has been completed” afterwards.

Part 2 – Executors

Using the getWebpage method implemented in Part 1, create an executor service which will handle getting 5 web pages simultaneously.

Part 3 – Performance

Investigate whether Parallel Streams gives a performance improvement on your own machine. Do you know how many cores you have in your CPU? What factor of improvement would you expect to see? For measuring execution time, you can use currentTimeMilis.

An example of code you can test on. Delete .parallel() to make it sequential.

static long countProbablePrimes(long n) {
    long count = LongStream.rangeClosed(2, n)
            .mapToObj(BigInteger::valueOf)
            .parallel() // request parallel processing
            .filter((i) -> i.isProbablePrime(50))
            .count();
 
    return count;
}

Part 4 – Incrementing in multithreading

Clone the starter repo here to your machine and follow the instructions in the README to run the app.

This code demonstrates how incrementing a counter with multiple threads can go wrong. Experiment with fixing it, first by using synchronized and then with an atomic variable.

Part 5 – Maps in multithreading

In multithreaded code the standard map paradigm of ‘test whether a value is in the map; if not, then add it’ isn’t safe, why not?