Process, thread

A Process is a running instance of a program. For example, a running Eclipse is a process. A process is the basic unit by which a program requests resources, such as memory space and file handles, from the operating system. A Thread is the smallest unit of a process that can execute independently. A process can contain multiple threads. The relationship between processes and threads is similar to the relationship between an open restaurant and its working employees.

1.1 Creating, starting, and running threads

There are two main ways to achieve multithreading in Java, one is to inherit Thread class, the other is to implement Runnable interface. (Callable and thread pools, of course). Below we will introduce the use of these two methods respectively, the rest please pay attention to this blog below.

(1). Class that inherits Thread

Public class PrimeThread extends Thread{public void run(){

for(int i = 0; i < 100; i++){ if(i % 2 == 0){ System.out.println(Thread.currentThread().getName() + "=" + i); }}}Copy the code

} public class TestThread {public static void main(String[] args) {PrimeThread p1 = new PrimeThread(); // Start a thread p1.start();

PrimeThread p2 = new PrimeThread(); p2.start(); for(int i = 0; i < 100; i++ ){ if(i % 2 == 0){ System.out.println(Thread.currentThread().getName() + "=" + i); }}}Copy the code

} (2). Implement Runnable interface

public class Ticket implements Runnable{

private int ticket = 100; @Override public void run() { while(ticket > 0){ System.out.println(Thread.currentThread().getName() + "=" + --ticket); }}Copy the code

} public class TestThread2 { public static void main(String[] args) {

Ticket ticket = new Ticket(); Threadt1 = new Thread(ticket," ticket window 1 "); t1.start(); Thread t2 = new Thread(ticket," ticket "); t2.start(); Thread t3 = new Thread(ticket," ticket "); t3.start(); }Copy the code

} A comparison of the two implementations:

1. From the perspective of object-oriented programming: The first creation method (inheriting the Thread class) is a basic inheritance technique, while the second creation method (directly creating the Thread instance through new with the Runnable interface instance as the constructor parameter) is a basic composition technique. The second approach will not only avoid the embarrassment of single inheritance, but also reduce the coupling between classes.

2. Object sharing perspective: The second creation method means that multiple thread instances can share the same Runnable instance. The first relies on the static keyword to do so.

1.2 Thread control

Java scheduling method

Threads of the same priority form a first-in, first-out queue (first-come, first-served) using a time slice policy

For high priorities, preemptive scheduling is used

Thread class related methods:

Sleep (long millis) : a static method in the Thread class that causes the current Thread to sleep join()/join(long millis) : an instance method that causes the current Thread to block Interrupts a blocked thread isAlive() : determines whether the current thread isAlive. Yield () : Public class TestThread3 {public static void main(String[] args) throws Exception {

Thread t1 = new Thread(new Runnable() { @Override public void run() { for(int i = 1; i < 100; i++){ if(i % 2 == 0){ System.out.println(Thread.currentThread().getName() + "=" + i); }}}}," thread 1"); t1.start(); // Thread 1 completes t1.sleep(10000); // The join method forces T2 to wait for thread 1 to finish executing. However, t1 is forced to wait 10 seconds after it outputs its own thread. Thread t2 = new Thread(new Runnable() { @Override public void run() { for(int i = 1; i < 100; i++){ if(i % 2 ! = 0){ System.out.println(Thread.currentThread().getName() + "=" + i); }}}}," thread 2"); t2.start(); }Copy the code

}

1.3 Thread Synchronization

Thread synchronization: simulate ticketing program to realize three Windows selling 100 tickets at the same time (1.1 cases)

Problem: When three Windows access shared data at the same time, there are multi-thread security issues such as disorder, duplication, overbooking, etc

Solution: “wrap” the shared data that needs to be accessed as a whole, ensuring that only one thread of execution flow can access the “shared data” at a time

Java provides several corresponding solutions to the above problem

(1). Synchronize code blocks

Synchronized {

// Shared data to be accessed

}

Synchronization monitor: colloquially known as “lock”, can be used as a reference to any object, taking care to ensure that multiple threads hold the same lock (same object)

(2). Synchronization method

Synchronized methods: add synchronized to the method declaration. Note: non-statically synchronized methods implicitly lock —- this

Such as:

public synchronized void show(){}

(3). Lock simultaneously

Synchronization Lock: Lock interface

Synchronized code block

public class SafeTicket implements Runnable{

private int ticket = 100; @override public void run() {while(true){synchronized (this) {if(ticket > 0){ System.out.println(thread.currentThread ().getName() + "+ --ticket"); }}}}Copy the code

} sync method:

public class SafeTicket implements Runnable{

private int ticket = 100; @override public void run() {while(true){public void run(); }} public synchronized void sale(){if(ticket > 0){system.out.println (thread.currentThread ().getname () +Copy the code

–ticket); }}

} synchronization lock

public class SafeTicket implements Runnable{

private int ticket = 100; private Lock l = new ReentrantLock(); @Override public void run() { while(true){ l.lock(); Try {if(ticket > 0){system.out.println (thread.currentThread ().getName() +Copy the code

–ticket); } } finally { l.unlock(); // release the lock}

}}Copy the code

} a deadlock

A deadlock is a phenomenon in which two or more processes are blocked during execution, either by competing for resources or by communicating with each other, and cannot proceed without external action. The system is said to be in a deadlock state or a deadlock occurs in the system. These processes that are always waiting for each other are called deadlocked processes

public class TestDeadLock { public static void main(String[] args) { final StringBuffer s1 = new StringBuffer(); final StringBuffer s2 = new StringBuffer();

    new Thread() {
        public void run() {
            synchronized (s1) {
                s2.append("A");
                
                try {
                    Thread.sleep(10);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                
                
                synchronized (s2) {
                    s2.append("B");
                    System.out.print(s1);
                    System.out.print(s2);
                }
            }
        }
    }.start();
    
    new Thread() {
        public void run() {
            synchronized (s2) {
                s2.append("C");
                synchronized (s1) {
                    s1.append("D");
                    System.out.print(s2);
                    System.out.print(s1);
                }
            }
        }
    }.start();
}
Copy the code

} 1.4 Thread communication

In the java.lang.Object class:

Wait () : Puts the current synchronization monitor thread into the wait state. Simultaneous lock release

Notify ()/notifyAll() : Wakes up (one/all) threads in the wait state on the current Synchronization monitor

Note: The above method must be used in synchronization

Scenario 1: Print 1-100 with two threads alternately thread 1 and thread 2

public class MyThread implements Runnable{

int i = 0;

@Override
public void run() {
    
    while(true){
        synchronized (this) {
            this.notify();
            
            if(i <= 100){
                System.out.println(Thread.currentThread().getName() + "=" + i++);
            }
            
            try {
                this.wait();
            } catch (InterruptedException e) {
            }
        }
        
    }
    
}
Copy the code

} public class TestThread4 { public static void main(String[] args) { MyThread myThread = new MyThread();

Thread t1 = new Thread(myThread," Thread 1"); Threadt2 = new Thread(myThread," thread2 "); t1.start(); t2.start(); }Copy the code

} classic example: producer/consumer problem

The Productor gives the product to the Clerk, and the Customer takes it from the Clerk, who can only hold a fixed number of products at a time (e.g., 20). If the producer tries to produce more products, the Clerk tells the producer to stop. Notify the producer to continue production if there is room in the store for the product; If there is no product in the store, the clerk will tell the consumer to wait, if there is a product in the store to inform the consumer to pick up the product. public class TestProduct {

public static void main(String[] args) {
    Clerk clerk = new Clerk();
    
    Productor pro = new Productor(clerk);
    Customer cus = new Customer(clerk);
    
    new Thread(pro).start();
    new Thread(cus).start();
}
Copy the code

}

// class Clerk {

private int product; Public synchronized void getProduct() {if (product >= 20) {system.out.println (" product is full! "); ); try { wait(); } catch (InterruptedException e) {}} else {system.out.println (InterruptedException e) {}} else {system.out.println (InterruptedException e); notifyAll(); }} public synchronized void saleProduct() {if (product <= 0) {system.out.println (" out! ); try { wait(); } catch (InterruptedException e) {}} else {system.out.println (" consumer "+ --product +" product "); notifyAll(); }}Copy the code

}

// Productor implements Runnable {

private Clerk clerk; public Productor() { } public Productor(Clerk clerk) { this.clerk = clerk; } public Clerk getClerk() { return clerk; } public void setClerk(Clerk clerk) { this.clerk = clerk; } @Override public void run() { while (true) { clerk.getProduct(); }}Copy the code

}

// consumer class Customer implements Runnable {

private Clerk clerk;

public Customer() {
}

public Customer(Clerk clerk) {
    this.clerk = clerk;
}

public Clerk getClerk() {
    return clerk;
}

public void setClerk(Clerk clerk) {
    this.clerk = clerk;
}

@Override
public String toString() {
    return "Customer [clerk=" + clerk + "]";
}

@Override
public void run() {
    while(true){
        clerk.saleProduct();
    }Copy the code