Java Multithreaded Recording (Including Cases)

Keywords: Java jvm Windows IE

Threads are the execution units of programs, execution paths.Is the most basic unit of CPU used by programs

Multithreaded -- Programs have multiple execution paths to improve usage of application processes

The more threads in the process, the higher the probability of seizing CPU execution rights.Thread execution is random

 

How Java programs work:

Starting a JVM from a Java command is like starting a process, which then creates a main thread to call the main method

JVM startup is multithreaded because garbage collection threads are also started, otherwise memory overflow is likely to occur.(GC thread and main thread)

 

Java multithreaded program:

Method 1: Inherit the Thread class, override the run() method, create objects, and execute objects.

Run() method: run() in the Thread class is used to contain code that is executed by threads (encapsulating code that is executed by threads) (run method is not called separately (direct call is common method), start())

start() method: The thread is started first, then the JVM calls the thread's run() method

Method 2: Implement the runnable interface

A: Custom class implements runnable

B: Override run() method

C: Create object of MyRunnable class

D: Create an object of the Thread class, passing the object of step C as a construction parameter

Solves the limitation of single inheritance in java, suits the situation that multiple identical program codes handle the same resource, separates the code with the same thread and data effectively

 

Some built-in methods:

public final String getName()   //Get Thread Name
public final String setName():    //Set Thread Name
public static Thread currentThread():    //Returns the currently executing thread object

 

Preemptive scheduling model (Java): Give priority to high priority threads using CPU s

public final int getPriority():   //Returns the priority of the thread object
public final void setPriority(): //Set Thread Priority

Priority range 1-10, default to 5, minimum 1, maximum 5

 

Thread control:

public static void sleep(long millis)    //Thread Sleep
public final void join():   //Thread Join (Waiting for Thread to Terminate))
public static void yield():  //Thread comity suspends the currently executing thread object and executes other threads
//Make the execution of multiple threads more harmonious, but not guaranteed
public final void setDaemon(boolean on):  //Set Daemon Thread
//When running threads are daemons, JVM Exit, this method must be called before starting the thread
public void interrupt(): //Break the thread, terminate its state, and throw a InterruptException

 

Thread life cycle: (illustration)

 

Thread synchronization: synchronized keyword

Package shared data code for multiple statement operations as a whole so that no one else executes a thread while it executes

Prerequisite: Multiple threads; Note: Multiple threads use the same lock object

Advantages: Solves multithreaded security issues

Disadvantages: When threads are equal, because each thread will determine the lock on synchronization, which is very resource-intensive, virtually reduces the efficiency of the program and is prone to deadlocks

Use Synchronization Code Block or Synchronization Method

 

Deadlock:

Examples of deadlock codes:

1 public class MyLock {
2     // Create two lock objects
3     public static final Object objA = new Object();
4     public static final Object objB = new Object();
5 }
 1 public class DeadLock extends Thread {
 2 
 3     private boolean flag;
 4 
 5     public DeadLock(boolean flag) {
 6         this.flag = flag;
 7     }
 8 
 9     @Override
10     public void run() {
11         if (flag) {
12             synchronized (MyLock.objA) {
13                 System.out.println("if objA");
14                 synchronized (MyLock.objB) {
15                     System.out.println("if objB");
16                 }
17             }
18         } else {
19             synchronized (MyLock.objB) {
20                 System.out.println("else objB");
21                 synchronized (MyLock.objA) {
22                     System.out.println("else objA");
23                 }
24             }
25         }
26     }
27 }
1 public class DieLockDemo {
2     public static void main(String[] args) {
3         DeadLock dl1 = new DeadLock(true);
4         DeadLock dl2 = new DeadLock(false);
5 
6         dl1.start();
7         dl2.start();
8     }
9 }

 

Waiting for wake-up mechanism:

The Object class provides three methods:

wait(): wait

notify(): wakes a single thread

notifyAll(): Wake up all threads

Why not in the Thread class: Because these methods must be called through a lock object, which can be any lock object, they are defined in the object class

 

Semaphore semaphore:

Semaphores, also known as semaphores, are used to coordinate threads in a multithreaded environment to ensure that they can use public resources correctly and reasonably.Semaphore maintains a license set for which we need to pass in a quantity value representing the number of threads that can access the shared resource at the same time when we initialize Semaphore.

Threads can obtain a license through the acquire() method and then operate on shared resources. Note that if the license set has been allocated, the thread will enter a waiting state until other threads have the opportunity to release a license. Thread release a license through the release() method and the license will be returned to Semaphore.

 

Multithreaded case:

Cinema ticket sales: There are 100 tickets in the cinema, and there are three windows to sell tickets, which simulate cinema ticket sales:

Using synchronous code blocks:

public class SellTicket implements Runnable {
    // Define 100 tickets
    private int tickets = 100;
    //Create Lock Object
    private Object obj = new Object();
    
    @Override
    public void run() {
        while (true) {
            synchronized (obj) {
                if (tickets > 0) {
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName()
                            + "Selling" + (tickets--) + "Tickets");
                }
            }
        }
    }
}
public class SellTicketDemo {
    public static void main(String[] args) {
        // Create Resource Object
        SellTicket st = new SellTicket();

        // Create three threaded objects
        Thread t1 = new Thread(st, "Window 1");
        Thread t2 = new Thread(st, "Window 2");
        Thread t3 = new Thread(st, "Window 3");

        // Start Thread
        t1.start();
        t2.start();
        t3.start();
    }
}

Using synchronization methods:

 1 package lab2;
 2 
 3 public class SellTicket implements Runnable {
 4 
 5     // Define 100 tickets
 6     private static int tickets = 100;
 7 
 8     @Override
 9     public void run() {
10         while (true) {
11             sellTicket();
12         }
13     }
14     
15      private synchronized void sellTicket() {
16             if (tickets > 0) {
17             try {
18                     Thread.sleep(100);
19             } catch (InterruptedException e) {
20                     e.printStackTrace();
21             }
22             System.out.println(Thread.currentThread().getName()
23                         + "Selling" + (tickets--) + "Tickets ");
24             }
25     }
26 }

Using the lock method:

 1 import java.util.concurrent.locks.Lock;
 2 import java.util.concurrent.locks.ReentrantLock;
 3 
 4 public class SellTicket implements Runnable {
 5 
 6     // Definition ticket
 7     private int tickets = 100;
 8 
 9     // Define Lock Object
10     private Lock lock = new ReentrantLock();
11 
12     @Override
13     public void run() {
14         while (true) {
15             try {
16                 // Locking
17                 lock.lock();
18                 if (tickets > 0) {
19                     try {
20                         Thread.sleep(100);
21                     } catch (InterruptedException e) {
22                         e.printStackTrace();
23                     }
24                     System.out.println(Thread.currentThread().getName()
25                             + "Selling" + (tickets--) + "Tickets");
26                 }
27             } finally {
28                 // Release lock
29                 lock.unlock();
30             }
31         }
32     }
33 
34 }

 

Ornamental Garden Problem: (using Bakery class) The garden has two swivel doors that allow access and monitor the number of people in the garden

Volatile keyword: Specifying a variable as volatile instructs the compiler to load and store the value of the variable at each use. More information can be found at https://www.cnblogs.com/daxin/p/3364014.html

Bakery Algorithm Bakery algorithm

Bakery.java

 1 package lab2;
 2 
 3 public class Bakery {
 4     public int nThreads;
 5     
 6     private volatile int[] ticket;
 7     private volatile boolean[] choosing;
 8     
 9     Bakery(int nTh) {
10         nThreads = nTh;
11         ticket = new int[nThreads];
12         choosing = new boolean[nThreads];
13         
14         for (int i = 0; i < nThreads; i++) {
15             System.out.println(i + ticket[1]);
16             ticket[i] = 0;
17             choosing[i] = false;
18         }
19     }
20     
21     private int getNextNumber() {
22         int largest = 0;
23         for (int i = 0; i < nThreads; i++) {
24             if (ticket[i] > largest)
25                 largest = ticket[i];
26         }
27         return largest + 1;
28     }
29     
30     private boolean isFavouredThread(int i, int j) {
31         if ((ticket[i] == 0) || (ticket[i] > ticket[j]))
32             return false;
33         else {
34             if (ticket[i] < ticket[j])
35                 return true;
36             else
37                 return (i < j);
38         }
39     }
40 
41     void wantToEnterCS(int threadID) {
42         choosing[threadID] = true;
43         ticket[threadID] = getNextNumber();
44         choosing[threadID] = false;
45         
46         for (int otherThread = 0; otherThread < nThreads; otherThread++) {
47             while(choosing[otherThread]) {
48                 // busy-wait
49             }
50             // Break any ties between threads
51             while (isFavouredThread(otherThread,threadID)) {
52                 // busy-wait
53             }
54         }
55     }
56 
57     void exitCS(int threadID) {
58         // Leave critical section
59         ticket[threadID] = 0;
60     }
61 }

Couter.java

 1 package lab2;
 2 
 3 public class Counter {
 4     volatile int value = 0;
 5 
 6     Counter() {
 7         System.out.println("TOTAL: " + value);
 8     }
 9 
10     boolean increment() {
11         int temp = value;   //read[v]
12         Simulate.HWinterrupt();
13         value = temp + 1;       //write[v+1]
14         System.out.println("TOTAL: " + value);
15             return true;
16     }
17 
18     boolean decrement() {
19         int temp = value;   //read[v]
20         Simulate.HWinterrupt();
21             if (temp == 0) return false;
22         Simulate.HWinterrupt();
23         value = temp - 1;       //write[v+1]
24         System.out.println("TOTAL: " + value);
25             return true;
26     }
27 }
28 
29 class Simulate {
30     public static void HWinterrupt() {
31         if (Math.random() < 0.5)
32            try{
33                Thread.sleep(200);
34            } catch(InterruptedException ie) {};
35     }
36 }

Turnstile.java

 1 package lab2;
 2 
 3 /* Notes:
 4  * No modifications need be made to the bakery class.  Instead, the turnstile
 5  * class and counter classes are adjusted to allow for "exit" turnstiles as well
 6  * as entrance turnstiles.  This solution incorporates a system to prevent the
 7  * number of people in the gardens from being negative, so the sleep call in
 8  * this class can be commented out.  Study the code in the Counter and Turnstile
 9  * classes to see how how this works.
10  * */
11 
12 public class Gardens {
13      static Turnstile west;
14      static Turnstile east;
15      static Turnstile westExit;
16      static Turnstile eastExit;
17      static Counter people;
18      static Bakery bakery;
19      
20     public static void main(String[] args) {
21         people = new Counter();
22         bakery = new Bakery(4);
23          
24          west = new Turnstile(0, true, people, bakery);
25          east = new Turnstile(1, true, people, bakery);
26 
27          westExit = new Turnstile(2, false, people, bakery);
28          eastExit = new Turnstile(3, false, people, bakery);
29          
30          west.start();
31          east.start();
32 
33         /* 
34         try {
35             Thread.sleep(5000);
36         } catch (InterruptedException e) {
37         }
38         */
39 
40         westExit.start();
41         eastExit.start();
42     }
43 }

Garden.java

 1 package lab2;
 2 
 3 public class Gardens {
 4      static Turnstile west;
 5      static Turnstile east;
 6      static Turnstile westExit;
 7      static Turnstile eastExit;
 8      static Counter people;
 9      static Bakery bakery;
10      
11     public static void main(String[] args) {
12         people = new Counter();
13         bakery = new Bakery(4);
14          
15          west = new Turnstile(0, true, people, bakery);
16          east = new Turnstile(1, true, people, bakery);
17 
18          westExit = new Turnstile(2, false, people, bakery);
19          eastExit = new Turnstile(3, false, people, bakery);
20          
21          west.start();
22          east.start();
23 
24         /* 
25         try {
26             Thread.sleep(5000);
27         } catch (InterruptedException e) {
28         }
29         */
30 
31         westExit.start();
32         eastExit.start();
33     }
34 }

 

Producer Consumer, Action List:

Buffer.java

 1 import java.util.LinkedList;
 2 import java.util.NoSuchElementException;
 3 
 4 class Buffer {
 5     LinkedList<Integer> queue = new LinkedList<Integer>();
 6     
 7     public synchronized void write(int i) {
 8         queue.add(i);
 9     }
10 
11     public synchronized int read() {
12         try {
13             return queue.removeFirst();
14         } catch(NoSuchElementException e) {
15             // the buffer is empty!?
16             return -1;
17         }
18     }
19 }

Producer.java

 1 class Producer implements Runnable {
 2     Buffer buffer;
 3 
 4     public Producer(Buffer b) {
 5         buffer = b;
 6     }
 7 
 8     public void run() {
 9         for(int i = 0; i < 20; i++) {
10             buffer.write(i);
11             System.out.println("Thread " + Thread.currentThread().getId() +
12                 " writes " + i);
13         }
14     }
15 }

Consumer.java

 1 class Consumer implements Runnable {
 2     Buffer buffer;
 3 
 4     public Consumer(Buffer b) {
 5         buffer = b;
 6     }
 7 
 8     public void run() {
 9         for(int i = 0; i < 10; i++) {
10             try {
11                 Thread.sleep(10);
12             } catch (InterruptedException e) {
13             }
14             int x = buffer.read();
15             System.err.println("Thread " + Thread.currentThread().getId() +
16                 " reads " + x);
17         }
18     }
19 }

InfBuffer.java

 1 public class InfBuffer {
 2     public static void main(String args[]) {
 3         Buffer b = new Buffer();
 4         Consumer c1 = new Consumer(b);
 5         Consumer c2 = new Consumer(b);
 6         Producer p = new Producer(b);
 7         (new Thread(c1)).start();
 8         (new Thread(c2)).start();
 9         (new Thread(p)).start();
10     }
11 }

 

Producer-consumer, modify the name and age of students and obtain: (can only be a dozen large pieces, can not be achieved after producer production wait for consumer consumption to produce)

1 public class Student {
2     String name;
3     int age;
4 }
 1 public class SetThread implements Runnable {
 2 
 3     private Student s;
 4     private int x = 0;
 5 
 6     public SetThread(Student s) {
 7         this.s = s;
 8     }
 9 
10     @Override
11     public void run() {
12         while (true) {
13             synchronized (s) {
14                 if (x % 2 == 0) {
15                     s.name = "Student1";
16                     s.age = 27;
17                 } else {
18                     s.name = "Student2"; 
19                     s.age = 30;
20                 }
21                 x++;
22             }
23         }
24     }
25 }
 1 public class GetThread implements Runnable {
 2     private Student s;
 3 
 4     public GetThread(Student s) {
 5         this.s = s;
 6     }
 7 
 8     @Override
 9     public void run() {
10         while (true) {
11             synchronized (s) {
12                 System.out.println(s.name + "---" + s.age);
13             }
14         }
15     }
16 }
 1 public class StudentDemo {
 2     public static void main(String[] args) {
 3         //Create Resources
 4         Student s = new Student();
 5         
 6         //Set and Get Classes
 7         SetThread st = new SetThread(s);
 8         GetThread gt = new GetThread(s);
 9 
10         //Thread Class
11         Thread t1 = new Thread(st);
12         Thread t2 = new Thread(gt);
13 
14         //Start Thread
15         t1.start();
16         t2.start();
17     }
18 }

 

Producer consumer, modify student name and age and get: (using Wait-to-wake mechanism to improve)

1 public class Student {
2     String name;
3     int age;
4     boolean flag;  //Add a tag, default is false,Indicates whether the producer generates a value
5 }
 1 public class SetThread implements Runnable {
 2 
 3     private Student s;
 4     private int x = 0;
 5 
 6     public SetThread(Student s) {
 7         this.s = s;
 8     }
 9 
10     @Override
11     public void run() {
12         while (true) {
13             synchronized (s) {
14                 //Determine if there is
15                 if(s.flag) {
16                     try {
17                         s.wait();
18                     } catch (InterruptedException e) {
19                         e.printStackTrace();
20                     }
21                 } 
22                 
23                 if (x % 2 == 0) {
24                     s.name = "Student1";
25                     s.age = 27;
26                 } else {
27                     s.name = "Student2"; 
28                     s.age = 30;
29                 }
30                 x++;
31                 
32                 //Modify Tags
33                 s.flag = true;
34                 //Wake Threads
35                 s.notify();
36             }
37         }
38     }
49 }
 1 public class GetThread implements Runnable {
 2     private Student s;
 3 
 4     public GetThread(Student s) {
 5         this.s = s;
 6     }
 7 
 8     @Override
 9     public void run() {
10         while (true) {
11             synchronized (s) {
12                 if (!s.flag) {
13                     try {
14                         s.wait();
15                     } catch (InterruptedException e) {
16                         e.printStackTrace();
17                     }
18                 }
19                 System.out.println(s.name + "---" + s.age);
20                 
21                 //Modify Tags
22                 s.flag = false;
23                 //Wake Threads
24                 s.notify();
25                 
26             }
27         }
28     }
29 }
public class StudentDemo {    //Ditto
    public static void main(String[] args) {
        //Create Resources
        Student s = new Student();
        
        //Set and Get Classes
        SetThread st = new SetThread(s);
        GetThread gt = new GetThread(s);

        //Thread Class
        Thread t1 = new Thread(st);
        Thread t2 = new Thread(gt);

        //Start Thread
        t1.start();
        t2.start();
    }
}

 

Toilet queuing (signal usage)

 1 import java.util.Random;
 2 import java.util.concurrent.Semaphore;
 3 
 4 class Wc extends Thread {
 5     private String name;
 6     private Semaphore wc;
 7     
 8     public Wc(String name, Semaphore wc) {
 9         this.name = name;
10         this.wc = wc;
11     }
12     
13     @Override
14     public void run() {
15         int availablePermit = wc.availablePermits();
16         if (availablePermit > 0) {
17             System.out.println(name+",Happy, I finally have a hole");
18         }else {
19             System.out.println(name+"There are no holes.");
20         }
21         
22         try {
23             wc.acquire();
24             System.out.println(name+",Happy, I finally got it!");
25             Thread.sleep(new Random().nextInt(1000));
26             System.out.println(name+",Cool, it's over at last!");
27             wc.release();
28         } catch (InterruptedException e) {
29 
30         }
31     }
32 }
33 
34 public class Demo {
35     public static void main(String[] args) {
36         Semaphore semaphore = new Semaphore(3);
37         
38         for (int i = 0; i < 10; i++) {
39             Wc wc = new Wc("No."+i+"personal", semaphore);
40             wc.start();
41         }
42     }
43 }

 

The Sleeping Barber

 1 import java.util.concurrent.Semaphore;
 2 
 3 public class Barber implements Runnable{
 4 
 5     Semaphore customerWaiting, seats, barberSleeping;
 6     
 7     Barber(Semaphore customerWaiting, Semaphore seats, Semaphore barberSleeping) {
 8         this.customerWaiting = customerWaiting;
 9         this.seats = seats;
10         this.barberSleeping = barberSleeping;
11     }
12     
13     public void run() {
14         
15         while (true){
16             
17             // Get a customer, sleep otherwise
18             try {
19                 customerWaiting.acquire();
20             } catch (InterruptedException e) {}
21 
22             // Cut the hair of the customer    
23             System.out.println("Cutting Hair");
24             barberSleeping.release();            
25             
26         }
27     }
28 }
 1 import java.util.concurrent.Semaphore;
 2 
 3 public class Customer implements Runnable{
 4 
 5     Semaphore customerWaiting, seats, barberSleeping;
 6 
 7     boolean cut = false;
 8     Customer(Semaphore customerWaiting, Semaphore seats, Semaphore barberSleeping) {
 9         this.customerWaiting = customerWaiting;
10         this.seats = seats;
11         this.barberSleeping = barberSleeping;
12 
13     }
14     
15     public void run() {
16         while (!cut) {
17             
18             // A random delay
19             // Don't want all the threads trying at once!
20             try {
21                 Thread.sleep((long)(Math.random()*100));
22             } catch (InterruptedException e1) {}
23             
24             // Try to get a seat in the waiting room
25             try {
26                 seats.acquire();
27             } catch (InterruptedException e) {}
28             System.out.println(seats.availablePermits());
29 
30                 System.out.println(Thread.currentThread().getName()+" is sitting down");
31                 // Try and wake barber
32                 customerWaiting.release();
33 
34                 
35                 // Get hair cut
36                 try {
37                     barberSleeping.acquire();
38                 } catch (InterruptedException e) {}
39                 cut = true;
40                 seats.release();
41             
42         }
43         System.out.println(Thread.currentThread().getName()+" has had hair cut");        
44     }
45 }
 1 import java.util.concurrent.Semaphore;
 2 
 3 public class Runner {
 4 
 5     public static void main(String[] args) {
 6         
 7         Semaphore barberSleeping = new Semaphore(1);
 8         Semaphore customerWaiting = new Semaphore(1);
 9         try {
10             customerWaiting.acquire();
11             barberSleeping.acquire();
12         } catch (InterruptedException e) {
13         }
14         
15         Semaphore seats = new Semaphore(3);
16         
17         Barber bar = new Barber(customerWaiting,seats,barberSleeping);
18         Thread bThread = new Thread(bar);
19         bThread.start();
20         
21         int nCust = 30;
22         Customer customers[] = new Customer[nCust];
23         Thread cThread[] = new Thread[nCust];
24         
25         for (int i=0;i<nCust;i++) {
26              customers[i] = new Customer(customerWaiting,seats,barberSleeping);
27              cThread[i] = new Thread(customers[i]);
28              cThread[i].start();
29         }
30     }
31 }

Posted by bogdan on Mon, 04 May 2020 23:59:15 -0700