Comparative analysis of two ways to realize multithreading

Since directly inheriting the Thread class and implementing the Runnable interface can achieve multithreading, what is the difference between these two ways of implementing multithreading in practical applications? Next, analyze through an application scenario

Suppose there are four windows in the ticket office that can sell 100 tickets for a certain train on a certain day. At this time, 100 tickets can be regarded as shared resources, and four ticket windows need to create four threads. In order to display the ticket sales of the window more intuitively, you can get the instance object of the current thread through the currentThread() method of Thread, and then call getName() to get the name of the thread. Next, first realize the creation of multiple threads by inheriting the Thread class.

public class Example1 {
    
    
	public static void main(String[] args) {
    
    
		new TicketWindow().start();   // 创建一个线程对象TicketWindow并开启
		new TicketWindow().start();   // 创建一个线程对象TicketWindow并开启
		new TicketWindow().start();   // 创建一个线程对象TicketWindow并开启
		new TicketWindow().start();   // 创建一个线程对象TicketWindow并开启
	}
}
class TicketWindow extends Thread {
    
    
	private int tickets = 100;
	public void run() {
    
    
		while (true) {
    
        // 通过死循环语句打印语句
			if (tickets > 0) {
    
    
				Thread th = Thread.currentThread(); // 获取当前线程
				String th_name = th.getName();       // 获取当前线程的名字
				System.out.println(th_name + " 正在发售第 " + tickets--+" 张票 ");
			}
		}
	}
}

Running result:
Insert picture description here
As can be seen from the above running result, each ticket has been printed four times. The reason for this phenomenon is that the four threads did not share 100 tickets, but each sold 100 tickets. Creating four Ticket Window objects in the program is equivalent to creating four ticketing programs. Each program has 100 tickets, and each thread is processing its own resources independently. It should be noted that each thread in Example 5-4 has its own name, the default name of the main thread is "main", the default name of the first thread created by the user is "Thread-0", and the second thread The default name is "Thread-1", and so on. If you want to specify the name of the thread, you can set the name for the thread by calling setName(String name).

Because the ticket resources in the railway system are shared in reality, the above operating results are obviously unreasonable. In order to ensure resource sharing, only one ticketing object can be created in the program, and then multiple threads can be opened to run the ticketing method of the same ticketing object. In simple terms, four threads run the same ticketing program. At this time, you need to use more The second way to implement threads. Modify the above example, and use the construction method Thread (Runnable target, String name) to specify the name of the thread while creating the thread object.

public class Example05 {
    
    
	public static void main(String[] args) {
    
    
		TicketWindow tw = new TicketWindow(); // 创建TicketWindow实例对象tw
		new Thread(tw, "窗口1").start();      // 创建线程对象并命名为窗口1,开启线程
		new Thread(tw, "窗口2").start();      // 创建线程对象并命名为窗口2,开启线程
		new Thread(tw, "窗口3").start();      // 创建线程对象并命名为窗口3,开启线程
		new Thread(tw, "窗口4").start();      // 创建线程对象并命名为窗口4,开启线程
	}
}
class TicketWindow implements Runnable {
    
    
	private int tickets = 100;

	public void run() {
    
    
		while (true) {
    
    
			if (tickets > 0) {
    
    
				Thread th = Thread.currentThread(); // 获取当前线程
				String th_name = th.getName(); // 获取当前线程的名字
				System.out.println(th_name + " 正在发售第 " + tickets-- + " 张票 ");
			}
		}
	}
}

Running result: In
Insert picture description here
example 2, only one TicketWindow object is created, and then four threads are created. On each thread, the run() method in this TicketWindow object is called, so that you can ensure that the four threads access the same one Ticket variable, sharing 100 tickets.
From the above two routines, it can be seen that implementing the Runnable interface has the following significant benefits compared to inheriting the Thread class:

  1. It is suitable for multiple threads of the same program code to deal with the same resource, effectively separating the thread from the program code and data, which well reflects the object-oriented design idea.
  2. You can avoid the limitations due to Java's single inheritance. In development, we often encounter such a situation, which is to use a subclass that has inherited a certain class to create a thread. Since a class cannot have two parent classes at the same time, the way of inheriting the Thread class cannot be used, so you can only Adopt the method of implementing Runnable interface.

In fact, most applications will use the second way to create multithreading, that is, to implement the Runnable interface.

Guess you like

Origin blog.csdn.net/xun08042/article/details/113513714