Slide 1

Slide 1 text

A N M Bazlur Rahman (@bazlur_rahman)

Slide 2

Slide 2 text

2022-06-09 @bazlur_rahman 2

Slide 3

Slide 3 text

PLEASE FASTEN YOUR SEAT BELT (WE ARE TAKING OFF) § What is a thread? § How to create a simple concurrent program § Identify the benefits of java threading § Understanding the bagasse that comes with threads and how to avoid them § What are the thread safe classes available in the JDK § This is a beginner-friendly workshop 2022-06-09 @bazlur_rahman 3

Slide 4

Slide 4 text

@bazlur_rahman 2022-06-09 4

Slide 5

Slide 5 text

§ From day 0, Java introduced Threads § Threads are units of execution in Java. § They are lightweight processes. § They share the memory spaces. 2022-06-09 @bazlur_rahman 5

Slide 6

Slide 6 text

§ If we have more CPU, threads improve performance (if the code is structured correctly) § Improved throughput (technically, more threads == more throughput) § Improves responsiveness; the whole program will not block, even though parts are. § Threads run on the same process, so resource sharing is easy (it has side effect as well) § Economy, we can use all CPUs. So no cpu cycles are wasted 2022-06-09 @bazlur_rahman 6

Slide 7

Slide 7 text

public class Main { public static void main(String[] args) { System.out.println("Im running on: " + Thread.currentThread()); } } //Im running on: Thread[main,5,main] 2022-06-09 @bazlur_rahman 7

Slide 8

Slide 8 text

public class MyThread extends Thread { @Override public void run() { System.out.println("A whole new world!"); } } 2022-06-09 @bazlur_rahman 8

Slide 9

Slide 9 text

var thread = new MyThread(); thread.start(); - The start() method does all the necessary initialization, then calls the run() 2022-06-09 @bazlur_rahman 9

Slide 10

Slide 10 text

public class MyRunnable implements Runnable{ @Override public void run() { System.out.println("A whole new world!"); } } MyRunnable myRunnable = new MyRunnable(); var thread = new Thread(myRunnable); thread.start(); 2022-06-09 @bazlur_rahman 10

Slide 11

Slide 11 text

var thread = new Thread(() -> { System.out.println("A new thread!"); }); thread.start(); 2022-06-09 @bazlur_rahman 11

Slide 12

Slide 12 text

§ Single-Threaded Web Server § Multithreaded Web Server @bazlur_rahman 2022-06-09 12

Slide 13

Slide 13 text

public static void main(String[] args) throws IOException { try (var server = new ServerSocket(8080)) { while (true) { var socket = server.accept(); handleRequest(socket); } } } private static void handleRequest (Socket socket) throws IOException { //rest of the codes } 2022-06-09 @bazlur_rahman 13

Slide 14

Slide 14 text

§ public static void main(String[] args) throws IOException { try (var server = new ServerSocket(8080)) { while (true) { var socket = server.accept(); new Thread(() -> { handleRequest(socket); }); } } } 2022-06-09 @bazlur_rahman 14

Slide 15

Slide 15 text

var thread = new Thread(() -> { try { TimeUnit.SECONDS.sleep(5); } catch (InterruptedException e) { System.err.println("Thread Interrupted deu to " + e.getMessage()); } throw new RuntimeException("Goodbye cruel world!"); }); thread.start(); thread.join(); We won’t see any Stack Trace for an exception here. 2022-06-09 @bazlur_rahman 15

Slide 16

Slide 16 text

§ thread.setUncaughtExceptionHandler((t, e) -> { e.printStackTrace(); }); 2022-06-09 @bazlur_rahman 16

Slide 17

Slide 17 text

§ Thread.stop() § Not safe. We should always avoid this one. 2022-06-09 @bazlur_rahman 17

Slide 18

Slide 18 text

§ We don’t! § Thread dies when the work is done 2022-06-09 @bazlur_rahman 18

Slide 19

Slide 19 text

@bazlur_rahman 2022-06-09 19

Slide 20

Slide 20 text

public class Playground { private static boolean running = false; public static void main(String[] args) { var t1 = new Thread(() -> { while (!running) { } System.out.println("Thread"); }); var t2 = new Thread(() -> { running = true; System.out.println("I love "); }); t1.start(); t2.start(); } } 2022-06-09 @bazlur_rahman 20

Slide 21

Slide 21 text

§ Linux : lscpu @bazlur_rahman 2022-06-09 21

Slide 22

Slide 22 text

2022-06-09 @bazlur_rahman 22

Slide 23

Slide 23 text

This is called a visibility problem. private volatile static boolean running = false; 2022-06-09 @bazlur_rahman 23

Slide 24

Slide 24 text

§ Caches are flushed immediately § Re-read from main memory before use § Or written back to main memory 2022-06-09 @bazlur_rahman 24

Slide 25

Slide 25 text

§ Read/Write from the exact memory location § Deposit & withdraw from a bank account § Write on a file from two different threads at the same. § If several threads access a memory location simultaneously, inconsistency appears, which is called a race condition. @bazlur_rahman 2022-06-09 25 Image: Head First Java, 3rd Edition

Slide 26

Slide 26 text

§ A Bank account accessing from multiple threads @bazlur_rahman 2022-06-09 26

Slide 27

Slide 27 text

public class BankAccount { private long balance; public BankAccount(long initialBalance) { this.balance = initialBalance; } public void deposit(long amount) { this.balance += amount; } public void withdraw(long amount) { this.deposit(-amount); } public long getBalance() { return balance; } } 2022-06-09 @bazlur_rahman 27

Slide 28

Slide 28 text

SOLUTION § We need a lock 2022-06-09 @bazlur_rahman 28

Slide 29

Slide 29 text

§ public class BankAccountWithLock { private long balance; private final Object lock = new Object(); public void deposit(long amount) { synchronized (lock) { this.balance += amount; } } public void withdraw(long amount) { synchronized (lock) { this.deposit(-amount); } } } 2022-06-09 @bazlur_rahman 29

Slide 30

Slide 30 text

§ IntCounter @bazlur_rahman 2022-06-09 30

Slide 31

Slide 31 text

§ public class IntCounter { private int count; public int incrementAndGet() { count = count + 1; return count; } public int getCount() { return count; } } 2022-06-09 @bazlur_rahman 31

Slide 32

Slide 32 text

public class IntCounter { private int count; public synchronized int incrementAndGet() { count = count + 1; return count; } public synchronized int getCount() { return count; } } 2022-06-09 @bazlur_rahman 32

Slide 33

Slide 33 text

§ When several threads compete over locks @bazlur_rahman 2022-06-09 33

Slide 34

Slide 34 text

final Object lockA = new Object(); final Object lockB = new Object(); Thread t1 = new Thread(() -> { synchronized (lockA) { sleep(); synchronized (lockB) { compute(); } } }); Thread t2 = new Thread(() -> { synchronized (lockB) { synchronized (lockA) { compute(); } } }); 2022-06-09 @bazlur_rahman 34

Slide 35

Slide 35 text

§ Avoid nested locking § Lock Ordering § Use Advance Locking (we won’t discuss today) Thread t1 = new Thread(() -> { synchronized (lockA) { sleep(); synchronized (lockB) { compute(); } } }); Thread t2 = new Thread(() -> { synchronized (lockA) { synchronized (lockB) { compute(); } } }); 2022-06-09 @bazlur_rahman 35

Slide 36

Slide 36 text

§ https://youtu.be/3cgZbACBpxI 2022-06-09 @bazlur_rahman 36

Slide 37

Slide 37 text

public final class Person { private final String name; private final int age; public Person(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } } 2022-06-09 @bazlur_rahman 37

Slide 38

Slide 38 text

§ Thread share memory space. That’s called shared mutable state. If multiple threads read/write shared data, that’s where we need to focus. § If we don’t need to change data (read-only), use an immutable object § All immutable objects are thread-safe § When we deal with a shared mutable state, we need to use a lock 2022-06-09 @bazlur_rahman 38

Slide 39

Slide 39 text

2022-06-09 @bazlur_rahman 39

Slide 40

Slide 40 text

§ AtomicInt § AtomicLong § AtomicBoolean § AtomicReference 2022-06-09 @bazlur_rahman 40

Slide 41

Slide 41 text

public class AtomicCounter { private AtomicInteger counter = new AtomicInteger(); public int incrementAndGet() { return counter.incrementAndGet(); } public int getCount() { return counter.get(); } } 2022-06-09 @bazlur_rahman 41

Slide 42

Slide 42 text

§ CopyOnWriteArrayList § BlockingQueue § ConcurrentHashMap § ConcurrentSkipListMap § ConcurrentSkipListSet 2022-06-09 @bazlur_rahman 42

Slide 43

Slide 43 text

2022-06-09 @bazlur_rahman 43

Slide 44

Slide 44 text

§ Creating threads Adhoc basic expensive § Threads are limited 2022-06-09 @bazlur_rahman 44

Slide 45

Slide 45 text

2022-06-09 @bazlur_rahman 45

Slide 46

Slide 46 text

§ Exectors.newFixedThreadPool(int nThreads): § Executors.newCachedThreadPool() § Executors.newSingleThreadExecutor() § Executors.newScheduledThredPool(int corePoolSize) 2022-06-09 @bazlur_rahman 46

Slide 47

Slide 47 text

2022-06-09 @bazlur_rahman 47

Slide 48

Slide 48 text

ExecutorService threadPool = Executors.newFixedThreadPool(10); try (var server = new ServerSocket(8080)) { while (true) { var socket = server.accept(); threadPool.submit(() -> { handleRequest(socket); }); } } 2022-06-09 @bazlur_rahman 48

Slide 49

Slide 49 text

§ Executors. shutdown() § Executors. shutdownNow() 2022-06-09 @bazlur_rahman 49

Slide 50

Slide 50 text

§ Runnable: when we don’t need a result § Callable: when we need results. 2022-06-09 @bazlur_rahman 50

Slide 51

Slide 51 text

2022-06-09 @bazlur_rahman 51

Slide 52

Slide 52 text

2022-06-09 @bazlur_rahman 52

Slide 53

Slide 53 text

2022-06-09 @bazlur_rahman 53

Slide 54

Slide 54 text

§ Java Concurrency in Practice - B. Goetz et al. § Concurrent Programming in Java - D. Lea § Optimizing Java - B. Evans et al. § https://foojay.io/today/author/bazlur-rahman/ § https://jenkov.com/tutorials/java-concurrency/index.html 2022-06-09 @bazlur_rahman 54

Slide 55

Slide 55 text

https://twitter.com/bazlur_rahman @bazlur_rahman 2022-06-09 55