JAVA ------ sincronización de subprocesos (explicación detallada del caso)

Veamos un caso primero:

Demanda : una sala de cine muestra actualmente películas de gran éxito nacional, con un total de 100 entradas, y tiene 3 ventanas para vender entradas, por favor diseñe un programa para simular la venta de entradas de la sala de cine.


Ideas:

  1. Defina un ticket de clase para implementar la interfaz Runnable,
    que define una variable miembro: private int tickets = 100;
  2. Vuelva a escribir el método run () en la clase de entrada para implementar la venta de
    entradas . Los pasos del código son los siguientes: A: Determine la cantidad de entradas para que sea mayor que 0, venda la entrada y diga en qué ventana
    vender la entrada . B: Después de que se vende el boleto, el número total de boletos se reducirá en 1
    C: si el boleto se ha ido, alguien puede venir a preguntar, por lo que aquí se usa un bucle infinito para mantener ejecutada la acción de venta de boletos
  3. Defina una clase de prueba con un método principal. Los pasos del código son los siguientes
    : A: Crea un objeto de la clase SellTicket
    B: Crea tres objetos de la clase Thread, usa el objeto SelITicke como parámetro del método de construcción
    y da el nombre de ventana correspondiente
    C: iniciar el hilo

Veamos una implementación preliminar:
clase de ticket:

package 卖票;
//定义一个类SellTicket实现Runnable接口,
//里面定义一个成员变量: private int tickets= 100;

public class ticket implements Runnable{
    
    
	private int tickets=100;
	
	@Override
	public void run() {
    
    
		//A:判断票数大于0,就卖票,并告知是哪个窗口卖的
		//B:卖了票之后,总票数要减1
		//C:票没有了,也可能有人来问,所以这里用死循环让卖票的动作一直执行
		while(true) {
    
    
			if(tickets>0) {
    
    
				int temp=101-tickets;
				System.out.println(Thread.currentThread().getName()+"正在出售第"+temp+"张票");
				tickets--;
			}
		}
	}

}

clase principal:

package 卖票;

/*
 * 需求:某电影院目前正在上映国产大片,共有100张票,
 * 而它有3个窗口卖票,请设计一个程序模拟该电影院卖票

思路:
1.	定义一个类SellTicket实现Runnable接口,
 	里面定义一个成员变量: private int tickets= 100;
2.	在ellTicket类中重写run()方法实现卖票, 代码步骤如下
A:判断票数大于0,就卖票,并告知是哪个窗口卖的
B:卖了票之后,总票数要减1
C:票没有了,也可能有人来问,所以这里用死循环让卖票的动作一直执行

3.	定义一个测试类, 里面有main方法,代码步骤如下
A:创建SellTicket类的对象
B:创建三个Thread类的对象,把SelITicke对象作为构造方法的参数,
	并给出对应的窗口名称
C:启动线程
 */


public class ticketDemo {
    
    
	public static void main(String[] args) {
    
    
		ticket t=new ticket();
		
		Thread t1=new Thread(t,"窗口一");
		Thread t2=new Thread(t,"窗口二");
		Thread t3=new Thread(t,"窗口三");
		
		t1.start();
		t2.start();
		t3.start();
		
	}

}


Después de ejecutarlo, encontrará que hay dos problemas con este programa:
1. Aparece un número negativo de boletos
2. Un boleto se vende varias veces

Se cumplen tres condiciones cuando ocurre el problema:

  1. ¿Es un entorno de subprocesos múltiples?
  2. ¿Hay intercambio de datos?
  3. Si hay varias declaraciones para operar y compartir datos.

Obviamente, aquí solo se puede romper la tercera condición.


Solución : bloquee el código para que varias declaraciones operen y compartan datos, de modo que solo se pueda ejecutar un hilo en cualquier momento (es decir, el acceso mutuamente exclusivo en el sistema operativo )

  • JAVA solo proporciona una forma de sincronizar bloques de código para resolver
  • Formato de bloque de código de sincronización:
synchronized (任意对象) {
    
    //相当于给代码加锁,任意对象就是一把锁
多条语句操作共享数据的代码
}

Veamos el código optimizado:
aquí está el método sleep () para simular el tiempo de emisión de boletos


Clase de entrada:

package 卖票;
//定义一个类SellTicket实现Runnable接口,
//里面定义一个成员变量: private int tickets= 100;

public class ticket implements Runnable{
    
    
	private int tickets=100;
	private Object obj=new Object();
	
	@Override
	public void run() {
    
    
		//A:判断票数大于0,就卖票,并告知是哪个窗口卖的
		//B:卖了票之后,总票数要减1
		//C:票没有了,也可能有人来问,所以这里用死循环让卖票的动作一直执行
		while(true) {
    
    
			synchronized (obj) {
    
    
			if(tickets>0) {
    
    
				//通过sleep()方法模拟出票时间
				try {
    
    
					Thread.sleep(100);
				} catch (Exception e) {
    
    
					e.printStackTrace();
				}
				int temp=101-tickets;
				System.out.println(Thread.currentThread().getName()+"正在出售第"+temp+"张票");
				tickets--;
			}
		}
	  }
	}

}

clase principal:

package 卖票;

/*
 * 需求:某电影院目前正在上映国产大片,共有100张票,
 * 而它有3个窗口卖票,请设计一个程序模拟该电影院卖票

思路:
1.	定义一个类SellTicket实现Runnable接口,
 	里面定义一个成员变量: private int tickets= 100;
2.	在ellTicket类中重写run()方法实现卖票, 代码步骤如下
A:判断票数大于0,就卖票,并告知是哪个窗口卖的
B:卖了票之后,总票数要减1
C:票没有了,也可能有人来问,所以这里用死循环让卖票的动作一直执行

3.	定义一个测试类, 里面有main方法,代码步骤如下
A:创建SellTicket类的对象
B:创建三个Thread类的对象,把SelITicke对象作为构造方法的参数,
	并给出对应的窗口名称
C:启动线程
 */


public class ticketDemo {
    
    
	public static void main(String[] args) {
    
    
		ticket t=new ticket();
		
		Thread t1=new Thread(t,"窗口一");
		Thread t2=new Thread(t,"窗口二");
		Thread t3=new Thread(t,"窗口三");
		
		t1.start();
		t2.start();
		t3.start();
		
	}

}


Como resultado, se realizan tres ventanillas de venta de boletos, y los boletos no se repiten ni son negativos, lo más importante es bloquear el proceso de venta de boletos para lograr el acceso exclusivo mutuo.

Supongo que te gusta

Origin blog.csdn.net/weixin_45102820/article/details/113762087
Recomendado
Clasificación