场景1:买票 多线程抢一些票
package com.wyh.thread; /** * @program: Thread * @description: 火车票抢票 * @author: 魏一鹤 * @createDate: 2021-12-25 00:18 **/ //发现问题 多个线程操作同一个资源的情况下 线程不安全了 数据混乱 public class TestThread3 implements Runnable { //票数 int ticketNums=10; @Override public void run() { //火车票抢票 while (true) { //如果没票了就停止 if(ticketNums<=0){ break; } //模拟延迟 try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } //Thread.currentThread().getName() 获取当前线程名称 我们是可以给线程命名的 System.out.println(Thread.currentThread().getName() + "-->抢到了"+ticketNums--+"张票"); } } public static void main(String[] args){ //创建runnable接口的实现类对象 TestThread3 testThread3 = new TestThread3(); //3个线程一起去抢票 new Thread(testThread3,"线程1").start(); new Thread(testThread3,"线程2").start(); new Thread(testThread3,"线程3").start(); } }
运行后发现 多个线程操作同一个资源的情况下 线程不安全了 数据混乱
场景2 :龟兔赛跑
首先来个赛跑距离 然后要距离离终点越来越近判断比赛是否结束,兔子需要睡觉,我们模拟兔子睡觉,让兔子的线程休眠,最终让乌龟胜利
package com.wyh.thread; /** * @program: Thread * @description: 龟兔赛跑 * @author: 魏一鹤 * @createDate: 2021-12-25 23:47 **/ public class TestThread4 implements Runnable{ //胜利者 private String winner; // 线程代码 @Override public void run() { //终点为100 for (int i = 0; i <= 100; i++) { //模拟兔子休息 如果线程名字是兔子,就让它睡觉 每十步也让兔子睡觉 if(Thread.currentThread().getName().equals("兔子")){ try { Thread.sleep(200); } catch (InterruptedException e) { e.printStackTrace(); } } boolean flag = gameOver(i); //如果比赛结束,就停止程序 if(flag){ break; } //打印线程名称 System.out.println(Thread.currentThread().getName() + "跑了"+i+"步"); } } //判断是否完成比赛 public boolean gameOver(int steps) { //判断是否有胜利者 如果有胜利者游戏结束 if(winner!=null){ return true; }{//如果步数为100 游戏结束 if (steps>=100){ //如果步数为100 把这个线程定义为胜利者 winner=Thread.currentThread().getName(); System.out.println("winner是:"+winner); return true; } } return false; } public static void main(String[] args){ //主程序 //定义赛道 TestThread4 race=new TestThread4(); //双线程开始跑步 new Thread(race,"兔子").start(); new Thread(race,"乌龟").start(); } }
通过这两个例子 就能简单的明白并发的必要性,如果没有并发控制,就会造成数据混乱