Introduction to Multithreading in Java

To understand threads, you must understand processes, so what is a process?
Process: The activity that occurs when a program is executed on a processor is called a process. A process is an executing program, an active entity, and a process is a "self-contained" running program , Has its own address space. Simply put, if my computer opens the ppt and word 2 programs, it is equivalent to 2 processes.
Thread: Thread is a lightweight process, the basic unit
thread used by the CPU belongs to a certain One process, one process has one or more threads.
Multiple threads share the same process resources
There are two types of
multitasking Process-based: The computer runs multiple processes at the same
time Thread-based: A process contains multiple threads
Features:
 Each process needs to allocate its own independent address space
 Inter-process calls involve more overhead than inter-thread communication
 Multiple threads can share the same address space and share the same process
together  The cost of switching between threads is more expensive than switching between processes Low
 Processes are heavyweight, threads are threads in a lightweight
JVM

  1. A
    process is created when the operating system starts (commands such as javac, java, javaw, etc.) JVM

  2. There are at least two threads in the JVM process: the main method and the garbage collection thread. They are
    called the main thread. Sometimes they start other threads. They must finally complete the execution and
    perform various shutdown and release actions.
    In Java, the thread is implemented. There are 3 ways,
    (1) Declare a subclass of the Thread class and override the run() method

     public class SampleThread extends Thread {
     		public void run( ) {/* 覆盖该方法*/ }
     		 }
      }
    

(2) Declare a class that implements the Runnable interface and implement the run() method

		public class SampleThread implements Runnable{
    				public void run( ) {
    				/* 实现该方法*/
    				 }
    	}

(3) Implement the Callable interface and implement his call method;

import java.util.concurrent.Callable;

public class Thread<V> implements Callable<V>{

	public V call() throws Exception {
		// TODO Auto-generated method stub
		return null;
	}
}
Callable<V> oneCallable = new SomeCallable<V>();   
//由Callable<Integer>创建一个FutureTask<Integer>对象:   
FutureTask<V> oneTask = new FutureTask<V>(oneCallable);   
//注释:FutureTask<Integer>是一个包装器,它通过接受Callable<Integer>来创建,它同时实现了Future和Runnable接口。 
  //由FutureTask<Integer>创建一个Thread对象:   
Thread oneThread = new Thread(oneTask);   
oneThread.start();   
//至此,一个线程就创建完成了。

It is worth noting that the first method of directly inheriting the Thread class is to directly rewrite the run method, that is, to turn yourself into a thread; and the second method is not a thread itself, and it implements the runnable interface. The run method in it only has the ability to specify how to run an empty thread.
Example code in the second way:
first define 2 threads; MyT1 and MyT2 (please create 3 classes by yourself to separate the following codes)

public class MyT1 extends Thread {
	@Override
	public void run() {
		for(int i = 0; i < 1000; i++) {
			System.out.println("aaaaa");
		}
	}
}
public class MyT2 extends Thread {
    	@Override
    	public void run() {
    		for(int i = 0; i < 1000; i++) {
    			System.out.println("bbbbb");
    		}
    	}
    }
public class Run {
	public static void main(String[] args) {
		System.out.println("main开始!");
		MyT1 t1 = new MyT1();
		MyT2 t2 = new MyT2();
		//设置线程优先级
		t1.setPriority(1);
		t2.setPriority(10);
		t1.start();
		t2.start();
		System.out.println("main结束!");
	}
}

The second way:
define 2 threads first; MyT1 and MyT2 (please create 3 classes by yourself to separate the following codes)

public class MyT1 implements Runnable {
	@Override
	public void run() {
		try {
			for(int i = 0; i < 10; i++) {
				System.out.println("aaaaa");
				Thread.currentThread().sleep(1000);
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
//此处MyT2和MyT1采用不同的写法
public class MyT2 implements Runnable {
	private Thread t = null;
	public MyT2() {
		this.t = new Thread(this);
		this.t.start();
	}
	@Override
	public void run() {
		try {
			for(int i = 0; i < 10; i++) {
				System.out.println("bbbbb");
				Thread.currentThread().sleep(2000);
			}
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
public class Run {
	public static void main(String[] args) {
		System.out.println("main开始!");
		//MyT1和MyT2的=run的方式也会有所不同
		Thread t1 = new Thread(new MyT1());
		t1.start();
		new MyT2();
		System.out.println("main结束!");
	}
}

Thread state:
New state (NEW): The thread that has not been started so far is in this state
 The newly created thread that has not called the Thread.start() method is in this state
. RUNNABLE: The thread state of the runnable thread. Call the start method
 A thread in a runnable state is running in the Java virtual machine, but it may be waiting for other resources in the operating system, such as the processor
locked state (wait state) (BLOCKED): the thread state of the blocked thread
 A thread in a blocked state is waiting for the monitor lock to enter a synchronized
block/method, or enter a synchronized block/method again after calling Object.wait()
 The locked state is divided into timing lock (given Time lock) and irregular lock (call sleep method)
termination state (TERMINATED): the thread state of the terminated thread. The thread has finished execution
2:
Insert picture description here
Insert picture description here
Method
in the thread 1.sleep() method Let the currently executing thread suspend execution within a specified time, but the "lock flag" will not be released. Not recommended. sleep() causes the current thread to enter a blocking state and will not execute within a specified time.
2.wait() method
Before other threads call the object's notify or notifyAll method, the current thread is caused to wait. The thread will release the "lock flag" it holds, so that other threads have a chance to seize the lock. The current thread must own the current object lock. If the current thread is not the owner of this lock, an IllegalMonitorStateException will be thrown.
The waiting thread that wakes up the current object lock using the notify or notifyAll method must also have the same object lock, otherwise an IllegalMonitorStateException will be thrown. waite() and notify() must be called in the synchronized function or synchronized block. If the call is made in a non-synchronized function or non-synchronized block, although it can be compiled and passed, an IllegalMonitorStateException will occur at runtime.
3. The yield method
suspends the currently executing thread object. Yield() only makes the current thread return to the executable state, so the thread that executes yield() may be executed immediately after entering the executable state. Yield() can only give threads of the same priority or higher priority a chance to execute.
4. The join method
waits for the thread to terminate. Wait for the thread that called the join method to end, and then continue execution. Such as: t.join();//Mainly used to wait for the end of the t thread, if there is no such sentence, main will be executed, resulting in unpredictable results.
Three: Thread priority (the ability of a thread to preempt the CPU)
If you do not set the priority, the default is 5, Java provides a priority of 1~10, 1 is the lowest, and 10 is the highest.
Setting the priority method:

final void setPriority(int newp) //: 修改线程的当前优先级
final int getPriority() //: 返回线程的优先级

Four: Thread synchronization
Sometimes two or more threads may try to access a resource at the same time. For example, one thread may try to read data from a file, while another thread tries to modify the data in the same file. In this case, the data It may become inconsistent; in order to ensure that a shared resource is only used by one thread at any point in time, "synchronization" must be used. Synchronization means that only one thread can access the same resource at the same time.
Two ways to complete synchronization:
(1 ) Synchronization method,

synchronized void methodA() { }

(2) Synchronization block

 synchronized(object) {
		//要同步的语句
}

Synchronization example:
First, create 3 new classes PrintM Student and Run
PrintM:

public class PrintM {
	public void print(String info) {
		System.out.print("[" + info);
		try {
			Thread.currentThread().sleep(1000);
			System.out.println("]");
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

Student :

public class Student extends Thread {
	private String name = null;
	private PrintM pm = null;
	public Student() {
		// TODO Auto-generated constructor stub
	}
	public Student(String n, PrintM p) {
		this.name = n;
		this.pm = p;
	}
	@Override
	public void run() {
		synchronized(this.pm) {
			this.pm.print(this.name);
		}
	}
}

In addition to this method (synchronization block), because we use a printer printM to print things, we can also add the print method in printM to the synchronization block keyword synchronized, (that is, the synchronization method)
Run:

 public class Run {
	public static void main(String[] args) {
		PrintM pm = new PrintM();
		Student s1 = new Student("rose", pm);
		Student s2 = new Student("jack", pm);
		Student s3 = new Student("peter", pm);	
		s1.start();
		s2.start();
		s3.start();
	}
}

When to use the synchronization method? Synchronization block?
There is only one situation we recommend to use the synchronization method: this class is written by yourself, and this method in this class will always be synchronized , and the synchronization block is basically used in other situations, which is beneficial Improve efficiency!
Five: wait-notify mechanism (allowing multiple threads to collaborate to do things) In
Java, inter-thread communication only provides 2 types/operations, wait () and wake up notify ((only notify the thread closest to yourself)) and notifyAll() (All threads wake up to do things, but only one with the highest priority can do it, and the rest of the threads still wait) because:
these three methods can only be used in synchronized methods (these methods are used as final methods in the Object class Implemented)
sample code: (production (bread) numbers, consumption numbers)
Number class:

public class Number {
	private int num = -1;
	private boolean numOk = false;
	/**
	 * 生成数字方法
	 * @param n 生成的数字
	 */
	public synchronized void putNum(int n) {
		if(numOk) {
			try {
				wait();
			} catch (InterruptedException e) {
				System.out.println("putNum()方法发生线程终断异常!");
				e.printStackTrace();
			}
		}
		this.num = n;
		this.numOk = true;
		System.out.println("生成数字:" + this.num);
//		try {
//			Thread.sleep(1000);
//		} catch (InterruptedException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
		notifyAll();
	}
	/**
	 * 得到数字方法
	 * @return 得到的数字
	 */
	public synchronized void getNum() {
		if(!numOk) {
			try {
				wait();
			} catch (InterruptedException e) {
				System.out.println("getNum()方法发生线程终断异常!");
				e.printStackTrace();
			}
		}
		System.out.println("得到数字:" + this.num);
		this.numOk = false;
//		try {
//			Thread.sleep(1000);
//		} catch (InterruptedException e) {
//			// TODO Auto-generated catch block
//			e.printStackTrace();
//		}
		notifyAll();
	}
}

produce class:

/**
 * 生成数字线程
 */
public class Produce implements Runnable {
	private int i = 0;
	private Number number = null;
	
	public Produce(Number n) {
		this.number = n;
		Thread t = new Thread(this, "produce");
		t.start();
	}
	public void run() {
		for(int j = 0; j < 10; j++) {
			this.number.putNum((i++) * 10);
		}
	}
}
Consume类:


  /**
 * 消费数字线程
 */
public class Consume implements Runnable {
	private Number number = null;
	
	public Consume(Number n) {
		this.number = n;
		Thread t = new Thread(this, "consume");
		t.start();
	}
	public void run() {
		for(int i = 0; i < 10; i++) {
			this.number.getNum();	
		}
	}
}

NumberRun class:

   public class NumberRun {

	public static void main(String[] args) {
		Number number = new Number();
		new Produce(number);
		new Consume(number);
	}
}

Finally, I give you a gadget made with threads: javaswing+threads, everyone can run and play!!
Three classes:
BallPanel class:

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Container;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
/**
 * 绘制界类
 * @author IBMT40
 *
 */
public class BallPanel extends JFrame {
	private JPanel mainPanel = new JPanel();
	private JPanel operatePanel = new JPanel();
	
	public BallPanel() {
		Container c = this.getContentPane();
		c.setLayout(new BorderLayout());
		this.mainPanel.setBackground(Color.BLACK);
		c.add(this.mainPanel, BorderLayout.CENTER);
		JButton b1 = new JButton("开始");
		b1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				Ball b = new Ball(mainPanel);
				b.start();
			}	
		});
		JButton b2 = new JButton("退出");
		b2.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				System.exit(0);
			}
		});
		this.operatePanel.add(b1);
		this.operatePanel.add(b2);
		c.add(this.operatePanel, BorderLayout.SOUTH);
		
		this.setSize(400, 400);
		this.setTitle("ball");
		this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		this.setVisible(true);
	}
}

Ball class:

import java.awt.Color;
import java.awt.Graphics;
import javax.swing.JPanel;
/**
 * 绘制小球线程
 * @author IBMT40
 *
 */
public class Ball extends Thread {
	
	private JPanel mainPanel = null;
	private int x = 0;
	private int y = 0;
	private int dx = 5;
	private int dy = 5;
	private int width = 20;
	private int height = 20;
	
	public Ball(JPanel p) {
		this.mainPanel = p;
	}
	
	public void run() {
		init();
		while(true) {
			try {
				Thread.sleep(20);
				Graphics g = this.mainPanel.getGraphics();
				g.setColor(Color.WHITE);
				//g.setXORMode(this.mainPanel.getBackground());
				g.setXORMode(Color.BLACK);
				
				g.fillOval(this.x, this.y, this.width, this.height);
				x = x + dx;
				y = y + dy;
				if(x > this.mainPanel.getWidth() - this.width) {
					dx = -dx;
				}
				if(y > this.mainPanel.getHeight() - this.height) {
					dy = -dy;
				}
				if(x < 0) {
					x = 0;
					dx = -dx;
				}
				if(y < 0) {
					y = 0;
					dy = -dy;
				}
				g.fillOval(x, y, this.width, this.height);
				g.dispose();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
	private void init(){
		Graphics graphics = this.mainPanel.getGraphics();
		graphics.setColor(Color.WHITE);
		graphics.fillOval(x, y, this.width, this.height);
		graphics.dispose();
	}
}

BallRun class:

 /**
 * 主程序
 * @author IBMT40
 *
 */
public class BallRun {
	public static void main(String[] args) {
		new BallPanel();
	}
}

Guess you like

Origin blog.csdn.net/lq1759336950/article/details/97826074