Java multithreading Foundation

Multithreading

1. Basic concepts: program, process and thread

  • Program: a set of instructions written in a language to complete a specific task
  • Process: an execution of a program, or a running program. For example, QQ and wechat are the units of resource allocation
  • Thread: a process can be further subdivided into threads. It is a path executed within a process. A process has at least one or more threads. Thread is the unit of calling and executing. Each thread has an independent running stack and program counter. Multiple threads share the method area and heap resources of the process.
  • Multithreading: for example, after running the QQ process, you can send files or download files at the same time.
  • Concurrency: in a time period, multiple tasks are carried out in sequence according to the allocated time slice
  • Parallel: multiple tasks are performed simultaneously in a time period

2. Creation and use of threads (4 ways)

  • Start method: start the thread and call the run method (the operation performed by the thread when it is scheduled)
  • 1. Inherit Thread class and override run() method
public static void main(String[] args) {
    //First kind
    FirstThread firstThread = new FirstThread();
   	firstThread.start();
	FirstThread firstThread1 = new FirstThread();
	firstThread1.start();

	//The second is through anonymous subclasses
	new Thread(){
    	@Override
    	public void run() {
        	for (int i = 0; i < 100 ; i++) {
            	if(i % 2 == 0){
                	System.out.println(i);
            	}
        	}
    	}
	}.start();

	//Third
	new FirstThread().start();
}
  • 2. Implement the Runnable interface and rewrite the run() method
/**
 * Implement Runnable interface
 * 1.Create a class object that implements the Runnable interface
 * 2.Create a Thread object and pass in the object created above through the Thread parameter constructor
 * 3.Call thread The start () method starts the thread
 */
MyRunnable myRunnable = new MyRunnable();
Thread thread = new Thread(myRunnable);
thread.start();

//The second method is not as good as the above method. If there are multiple threads, there will be multiple objects and waste resources
new Thread(new myRunnable()).start();
  • Common thread methods
public static void main(String[] args) {
    /**
     * 1.start() Start the thread and call the run method to perform relevant operations
     * 2.Thread.currentThread.getName() Gets the current thread name
     * 3.setName() Set current thread name
     * 4.getName() Gets the current thread name
     * 5.yield() Release current cpu execution rights
     * 6.join() Thread A calls the join method of thread B. thread A enters the blocking state. Thread A does not end the blocking state until the execution of thread B is completed
     */
    MyThreadApi myThreadApi = new MyThreadApi();

    //1.start() starts the thread and calls the run method to perform related operations
    new Thread(new MyThreadApi()).start();
    myThreadApi.start();

    //2.Thread.currentThread.getName() gets the current thread name
    //2.1 get the thread name in the current main method
    Thread.currentThread().getName();
    //2.2 get the Thread name of the class object that inherits the Thread class
    myThreadApi.currentThread().getName();

    //3.setName set thread name
    //3.1 set the thread name for the current main method
    Thread.currentThread().setName("Main thread:");
    //3.2 set the Thread name for the object that inherits the Thread class
    myThreadApi.setName("I am myThreadApi Threads:");
}
Comparison of two ways to realize multithreading
  • 1. The Runnable interface mode is preferred in development:
  • A. No single inheritance limitations
  • B. It is more suitable for processing data shared by multiple threads

3 thread life cycle

4 thread synchronization (synchronization code block, synchronization method, Lock lock [lock(),unlock() method])

  • Implement Runnable interface to solve thread safety problems (code block)
/**
 * Runnable Thread safety is realized by synchronizing code blocks
 */
private int ticket = 100;
private Object obj = new Object();
@Override
public void run() {
        while (true){
            //synchronized(this)
    		synchronized(obj){
            if(ticket > 0){
                ticket--;
                System.out.println(Thread.currentThread().getName() + "Ticket purchase succeeded! Remaining votes:" + ticket);
            }else {
                break;
            }
        }
    }
}

    public static void main(String[] args) {
        RunnableTicket runnableTicket = new RunnableTicket();
        new Thread(runnableTicket).start();
        new Thread(runnableTicket).start();
    }
  • Synchronization method plus synchronized keyword
/**
 * Runnable Thread safety is realized by synchronous method
 */
private int ticket = 100;
@Override
public void run() {
    while(true){
    	show();  
    }
}

private synchronized void show(){
        if(ticket > 0){
            ticket--;
            System.out.println(Thread.currentThread().getName() + "Ticket purchase succeeded! Remaining votes:" + ticket);
        }else {
            break;
        }
}
  • Inherit Thread to solve Thread safety problems (code block)
private static int ticket = 100;
private static Object obj = new Object();
@Override
public void run() {
        while (true){
            //synchronized(ThreadTick.class)
    		synchronized(obj){
            if(ticket > 0){
                ticket--;
                System.out.println(Thread.currentThread().getName() + "Ticket purchase succeeded! Remaining votes:" + ticket);
            }else {
                break;
            }
        }
    }
}

public static void main(String[] args) {
	new ThreadTicket().start();
	new ThreadTicket().start();
}
  • Synchronization method
private static int tickets = 100;
@Override
public void run() {
    while (true){
        show();
    }
}

/**
 * Because static methods are loaded as classes load and only once, locks are unique
 *
 * Extended review: static code blocks are loaded with the loading of classes and are actively executed
 *           Non static code blocks are loaded with the creation of class objects and are actively executed
 */
private static synchronized void show(){
    if(tickets > 0){
        tickets--;
        System.out.println("Ticket sales successful! Current passenger:" + Thread.currentThread().getName() + ",Remaining votes:" + tickets);
    }else {
        return;
    }
}
  • Example: two accounts remit 3000 yuan to another account, three times in total
public class ImportMoney {
    private static int money = 0;
	//The third type: Object obj = new Object()
    
    //First kind
    public synchronized void getMoney(int getMoney){
        if(getMoney > 0){
            money += getMoney;
            System.out.println("Current balance: " + money + ",Remittance account:" + Thread.currentThread().getName());
        }else {
            return;
        }
    }
    
    //Second
    public void getMoney(int getMoney){
        synchronized(this){
            if(getMoney > 0){
                money += getMoney;
                System.out.println("Current balance: " + money + ",Remittance account:" + Thread.currentThread().getName());
            }else {
                return;
            }
        }
    }
    
    //The third way is to synchronize (obj) through the object monitor
}




public class ImportMoneyTest {
    public static void main(String[] args) {
        //The current class object in is the only lock
        ImportMoney in = new ImportMoney();
        new Export(in).start();
        new Export(in).start();
    }
}


class Export extends Thread{
    //As the only lock
    private ImportMoney importMoney;

    public Export(ImportMoney importMoney){
        this.importMoney = importMoney;
    }

    @Override
    public void run() {
        for (int i = 0; i <3 ; i++) {
            importMoney.getMoney(1000);
        }
    }
}

5 thread communication

public class MyWait implements Runnable {
    private int num = 1;
    @Override
    public void run() {
        while (true){
            synchronized (this){
                //Wake up the thread entering the block
                notify();
                if(num <= 100){
                    System.out.println(Thread.currentThread().getName() + ":" + num);
                    num++;
                    try {
                        //Enter the blocking state and release the cpu execution right, but sleep() will not release. It is consistent in the blocking resource occupying state
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }else {
                    break;
                }
            }
        }
    }
}

6 JDK5.0 new thread creation methods (4 in total)

  • 3. Implement Callable interface
    public class MyCallable implements Callable {
        @Override
        public Object call() throws Exception {
            int num = 10;
            return num;
        }
    }
    
    
    public class MyCallableTest  {
        public static void main(String[] args) {
            //3. Create an object of the Callable interface implementation class
            MyCallable myCallable = new MyCallable();
            //4. Pass the object of this Callable interface implementation class as a parameter to the FutureTask constructor to create a FutureTask object
            FutureTask futureTask = new FutureTask(myCallable);
            //5. Take futureTask as a parameter and start the Thread through Thread
            new Thread(futureTask).start();
    
            try {
                //6. Get the return value of call method in Callable
                Object o = futureTask.get();
                System.out.println(o);
            } catch (InterruptedException e) {
                e.printStackTrace();
            } catch (ExecutionException e) {
                e.printStackTrace();
            }
        }
    }
    

Keywords: Java

Added by cjosephson on Sat, 25 Dec 2021 10:54:19 +0200