Lesson 3

Threads I

Sometimes there is a need to do few things at the same time e.g. cheating during the exam and checking the position of the examiner. With a usage of threads different instructions can be executed concurrently (e.g. two loops are executed at the same time).

I. Thread Class


// Creating a new thread:
Thread thread0 = new Thread(new Runnable() {
    public void run() {
        // code
    }
});

// Let’s try to write the same but this time using lambda expression
Thread thread1 = new Thread(() -> {
    // code
});

// Thread has to be started.
// Creating an object is not enough.
thread0.start();
thread1.start();
Task 0

Create 2 threads. First will print digits from 0 do 9 with a usage of System.out, second will do the same but with a usage of System.err. Let those threads print 20 series of digits.

Use print method instead of println.

Execute the program few times. Are the results the same or different? Why?

Task 1

Create a loop which will print numbers from 0 to 1 000 000.

Next check how much time the program needs to be finished. You can use System.currentTimeMillis() method, that returns a number of milliseconds from 1st January 1970 0:00 UTC.

We are looking for the difference between the time before and after executing a loop.

Save time results for 3 attempts (e.g. on paper, in a text file)

Next create 2 threads. First one will print even numbers, second one will print odd numbers from the range [0,1 000 000].
Each thread will print how much time it needed to execute its loop.

Save time results for 3 attempts and compare them with the previous implementation (without threads).

II. Java Memory Model (JVM)

III. Concurrent instructions executing


Task 2

Analyze the code below. What do expect as a result?

Execute the program few Times.

Which fragment is critical? Which thread cannot be interwaved with executing other thread.

Add a keyword "synchronized" in proper place (there are 2 possibilities).

class AddingThread extends Thread {

    private Counter c;

    public AddingThread(Counter c) {
        this.c = c;
    }

    public void run() {
        for (int i = 0; i < 1000; i++) {
            c.inc(i);
        }
    }
}

class Counter {
    private int x = 0;
    void inc(int value) {
        int sum = x + value;
        x = sum;
    }
    public String toString() {
        return x + "";
    }
}

public class Main {

    public static void main(String[] args) {
        Counter c = new Counter();
        AddingThread at0 = new AddingThread(c);
        at0.start();
        AddingThread at1 = new AddingThread(c);
        at1.start();
        AddingThread at2 = new AddingThread(c);
        at2.start();
        System.out.println("Counter.x=" + c);
    }
}
synchronized keyword
  1. It can be written before declaring returning type of a method.
  2. It can be used as a block.
  3. If synchronized is used then a block of instructions is treated as ”cannot be interrupted".
// synchronized for a method
public synchronized void method() {
    //...
}

// synchronized for an object
synchronized(object) {
    //...
}
Task 3

Create a class named Account(long balance). It is a representation of a bank account with the information about its balance.

Bank is an entity which contains its funds, sum of all accounts’ balances. Let’s say we have 2 accounts with balance 10 000 each.

Task is to do concurrently 8 transactions (on those 2 accounts) using random amount of money.

When all the transactions are calculated, sum of balances for all the accounts should be the same as at the beginning.