问题代码:
public class Ticket implements Runnable { //实现Runnable接口 创建多线程 引发 线程安全问题 private int tickets=100; public void run() { while(true) { try { if(tickets>0) { Thread.sleep(10); //使线程休眠 String name=Thread.currentThread().getName(); //获取当前线程的名称 System.out.println(name+"正在发售第"+ tickets-- +"张票"); }else { break; } } catch (InterruptedException e) { e.printStackTrace(); } } } }
测试类
public static void main(String[] args) { Ticket ticket= new Ticket(); //创建线程任务 Thread t1 = new Thread(ticket,"窗口1"); // 定义4个线程对象,代表4个售票窗口 Thread t2 = new Thread(ticket,"窗口2"); Thread t3 = new Thread(ticket,"窗口3"); Thread t4 = new Thread(ticket,"窗口4"); t1.start(); //开启四个线程 t2.start(); t3.start(); t4.start(); }
结果:
从运行结果看,不合逻辑 出现负数 ...
解决方式一: 使用同步代码块
public class Ticket implements Runnable { //解决线程安全问题,使用 同步代码块(同步锁) private int tickets=100; public void run() { while(true) { synchronized(this) { //将this设置为 锁对象 try { if(tickets>0) { Thread.sleep(10); //使线程休眠 String name=Thread.currentThread().getName(); //获取当前线程的名称 System.out.println(name+"正在发售第"+ tickets-- +"张票"); }else { break; } } catch (InterruptedException e) { e.printStackTrace(); } } } } }
测试代码:
public static void main(String[] args) { Ticket ticket= new Ticket();//创建线程任务 // 定义4个线程对象,代表4个售票窗口 Thread t1 = new Thread(ticket,"窗口1"); Thread t2 = new Thread(ticket,"窗口2"); Thread t3 = new Thread(ticket,"窗口3"); Thread t4 = new Thread(ticket,"窗口4"); //开启四个线程 t1.start(); t2.start(); t3.start(); t4.start(); }
问题得到解决:
方式二:使用同步方法
public class Ticket implements Runnable { //解决线程安全问题 使用 同步方法 private int tickets=100; public void run() { while(true) { saleTicket(); //调用售票方法 if(tickets<=0) { break; } } } private synchronized void saleTicket() { //定义一个同步方法 saleTicket() if(tickets>0) { try { if(tickets>0) { Thread.sleep(10); //使线程休眠10ms String name=Thread.currentThread().getName(); //获取当前线程的名称 System.out.println(name+"正在发售第"+ tickets-- +"张票"); } } catch (InterruptedException e) { e.printStackTrace(); } } } }
测试类:
public static void main(String[] args) { Ticket ticket= new Ticket(); //创建线程任务 Thread t1 = new Thread(ticket,"窗口1"); // 定义4个线程对象,代表4个售票窗口 Thread t2 = new Thread(ticket,"窗口2"); Thread t3 = new Thread(ticket,"窗口3"); Thread t4 = new Thread(ticket,"窗口4"); t1.start(); //开启四个线程 t2.start(); t3.start(); t4.start(); }
原文:https://www.cnblogs.com/penguin1024/p/11781534.html