三个售票窗口同时出售20张票

** (1)票数要使用同一个静态值
(2)为保证不会出现卖出同一个票数,要java多线程同步锁。
设计思路:
(1)创建一个站台类Station,继承Thread,重写run方法,在run方法里面执行售票操作!售票要使用同步锁:即有一个站台卖这张票时,其他站台要等这张票卖完!
(2)创建主方法调用类

站台类:

  1. package java_multi_thread.sell_ticket_example;
  2. /**
  3. * Created by hasee
  4. * on 2019/12/12 20:52
  5. * 站台类,继承thread
  6. */
  7. public class Station extends Thread {
  8. //通过构造方法给线程名字赋值
  9. public Station(String name){
  10. super(name);//为线程名字赋值
  11. }
  12. //为保持票数的一致,票数要静态
  13. public static int tick = 30;
  14. //创建一个静态方法
  15. public static Object ob = 't';//值可以任意
  16. //重写run方法,实现买票操作
  17. @Override
  18. public void run(){
  19. while(tick > 0){
  20. synchronized (ob) {//同步锁
  21. // 进去买票的人会把钥匙拿在手上,出来后才把钥匙拿让出来
  22. if(tick > 0){
  23. System.out.println(getName()+"卖出了"+tick+"张票");
  24. tick --;
  25. }else{
  26. System.out.println("票已售空!");
  27. }
  28. }
  29. try {
  30. sleep(1000);
  31. }catch (InterruptedException e){
  32. e.printStackTrace();
  33. }
  34. }
  35. }
  36. }

执行类:

  1. package java_multi_thread.sell_ticket_example;
  2. /**
  3. * Created by hasee
  4. * on 2019/12/12 21:01
  5. *
  6. * java多线程同步锁的使用
  7. * 三个窗口同时售票
  8. */
  9. public class MainClass {
  10. public static void main(String[] args){
  11. //实例化站台
  12. Station station1 = new Station("1号窗口");
  13. Station station2 = new Station("2号窗口");
  14. Station station3 = new Station("3号窗口");
  15. //让每一个对象各自开始工作
  16. station1.start();
  17. station2.start();
  18. station3.start();
  19. }
  20. }

两个人AB通过一个账户A在柜台取钱和B在ATM机取钱

钱的数量要设置成一个静态的变量,两个人要取的同一个对象值
银行类:

  1. package java_multi_thread.two_person_user_atm_example;
  2. import java.util.Objects;
  3. /**
  4. * Created by hasee
  5. * on 2019/12/12 21:12
  6. */
  7. public class Bank {
  8. //设定一个账户余额
  9. public static int money = 3000;
  10. //在柜台取钱
  11. public void counter(double money){
  12. Bank.money -= money;
  13. System.out.println("从柜台取钱--"+"账户余额:"+Bank.money);
  14. }
  15. //在ATM取钱
  16. public void atm(double money){
  17. Bank.money -=money;
  18. System.out.println("从ATM取钱--"+"账户余额"+Bank.money);
  19. }
  20. //提供一个对外取款途径,防止直接调取方法同时取款时,并发余额显示错误
  21. public synchronized void outMoney(double money,String mode) throws Exception{
  22. if(Bank.money < money){
  23. throw new Exception("取款金额:"+money+",您的账户余额:"+Bank.money+",取款失败!");
  24. }
  25. if(Objects.equals(mode,"atm")){
  26. atm(money);
  27. }else{
  28. counter(money);
  29. }
  30. }
  31. }

取钱人A:

  1. package java_multi_thread.two_person_user_atm_example;
  2. /**
  3. * Created by hasee
  4. * on 2019/12/12 21:23
  5. */
  6. public class PersonA extends Thread{
  7. Bank bank;
  8. String mode;
  9. public PersonA(Bank bank,String mode){
  10. this.bank = bank;
  11. this.mode = mode;
  12. }
  13. public void run(){
  14. while (bank.money >= 100){
  15. try {
  16. bank.outMoney(100,mode);
  17. }catch (Exception e1){
  18. e1.printStackTrace();
  19. }
  20. try {
  21. sleep(1000);
  22. }catch (InterruptedException e2){
  23. e2.printStackTrace();
  24. }
  25. }
  26. }
  27. }

取钱人B:

  1. package java_multi_thread.two_person_user_atm_example;
  2. /**
  3. * Created by hasee
  4. * on 2019/12/12 21:28
  5. */
  6. public class PersonB extends Thread{
  7. Bank bank;
  8. String mode;
  9. public PersonB(Bank bank,String mode){
  10. this.bank = bank;
  11. this.mode = mode;
  12. }
  13. public void run(){
  14. while (bank.money >= 100){
  15. try {
  16. bank.outMoney(350,mode);
  17. }catch (Exception e1){
  18. e1.printStackTrace();
  19. }
  20. try {
  21. sleep(1000);
  22. }catch (InterruptedException e2){
  23. e2.printStackTrace();
  24. }
  25. }
  26. }
  27. }

执行类:

  1. package java_multi_thread.two_person_user_atm_example;
  2. /**
  3. * Created by hasee
  4. * on 2019/12/12 21:28
  5. */
  6. public class MainClass {
  7. public static void main(String[] args){
  8. Bank bank = new Bank();
  9. //实例化PersonA、B,传入同一个银行bank
  10. PersonA personA = new PersonA(bank,"atm");
  11. PersonB personB = new PersonB(bank,"counter");
  12. personA.start();
  13. personB.start();
  14. }
  15. }

龟兔赛跑问题

龟兔赛跑:2000米
要求:
(1)兔子每 0.1 秒 5 米的速度,每跑20米休息1秒;
(2)乌龟每 0.1 秒跑 2 米,不休息;
(3)其中一个跑到终点后另一个不跑了!
程序设计思路:
(1)创建一个Animal动物类,继承Thread,编写一个running抽象方法,重写run方法,把running方法在run方法里面调用。
(2)创建Rabbit兔子类和Tortoise乌龟类,继承动物类
(3)两个子类重写running方法
(4)本题的第3个要求涉及到线程回调。需要在动物类创建一个回调接口,创建一个回调对象。

动物类:抽象类(abstract)

  1. package java_multi_thread.animal_race;
  2. /**
  3. * Created by hasee
  4. * on 2019/12/12 21:42
  5. */
  6. public abstract class Animal extends Thread {
  7. public int length = 500;
  8. public abstract void runing();
  9. @Override
  10. public void run(){
  11. super.run();
  12. while (length > 0){
  13. runing();
  14. }
  15. }
  16. // 在需要回调数据的地方(两个子类需要),声明一个接口
  17. public static interface Calltoback{
  18. public void win();
  19. }
  20. //创建接口对象
  21. public Calltoback calltoback;
  22. }

乌龟类:

  1. package java_multi_thread.animal_race;
  2. /**
  3. * Created by hasee
  4. * on 2019/12/12 21:50
  5. */
  6. public class Tortoise extends Animal {
  7. public Tortoise(){
  8. setName("Tortoise");
  9. }
  10. @Override
  11. public void runing() {
  12. //乌龟的速度
  13. int speed = 2;
  14. length -= speed;
  15. System.out.println("兔子跑了"+speed+"米,距离终点还有"+length+"米");
  16. if(length <= 0){
  17. length = 0;
  18. System.out.println("乌龟获得胜利");
  19. //给回调对象赋值,让兔子别跑了
  20. if(calltoback != null){
  21. calltoback.win();
  22. }
  23. }
  24. try {
  25. sleep(100);//每0.1秒跑2米
  26. }catch (InterruptedException e){
  27. e.printStackTrace();
  28. }
  29. }
  30. }

兔子类:

  1. package java_multi_thread.animal_race;
  2. /**
  3. * Created by hasee
  4. * on 2019/12/12 21:45
  5. */
  6. public class Rabbit extends Animal {
  7. public Rabbit(){
  8. setName("Rabbit");
  9. }
  10. @Override
  11. public void runing() {
  12. //兔子的速度
  13. int speed = 5;
  14. length -= speed;
  15. System.out.println("兔子跑了"+speed+"米,距离终点还有"+length+"米");
  16. if(length <= 0){
  17. length = 0;
  18. System.out.println("兔子获得胜利");
  19. //给回调对象赋值,让乌龟别跑了
  20. if(calltoback != null){
  21. calltoback.win();
  22. }
  23. }
  24. try {
  25. if((2000 - length)%20 ==0){// 每20米休息一次,休息时间是1秒
  26. sleep(1000);
  27. }else{
  28. sleep(100);//每0.1秒跑5米
  29. }
  30. }catch (InterruptedException e){
  31. e.printStackTrace();
  32. }
  33. }
  34. }

静止类:(判断是否已有胜者)

  1. package java_multi_thread.animal_race;
  2. /**
  3. * Created by hasee
  4. * on 2019/12/12 21:52
  5. */
  6. public class LetOneStop implements Animal.Calltoback {
  7. //动物
  8. Animal animal;
  9. //获取动物对象,可以传入乌龟或者兔子的实例
  10. public LetOneStop(Animal animal){
  11. this.animal = animal;
  12. }
  13. @Override
  14. public void win() {
  15. //让线程停止
  16. animal.stop();
  17. }
  18. }

执行类:

  1. package java_multi_thread.animal_race;
  2. /**
  3. * Created by hasee
  4. * on 2019/12/12 21:52
  5. */
  6. public class MainClass {
  7. public static void main(String[] args){
  8. //实例化动物
  9. Rabbit rabbit = new Rabbit();
  10. Tortoise tortoise = new Tortoise();
  11. //回调方法的使用,谁先使用calltoback方法,另一个就停下
  12. LetOneStop letOneStop1 = new LetOneStop(tortoise);
  13. // 让兔子的回调方法里面存在乌龟对象的值,可以把乌龟stop
  14. rabbit.calltoback = letOneStop1;
  15. LetOneStop letOneStop2 = new LetOneStop(rabbit);
  16. // 让乌龟的回调方法里面存在兔子对象的值,可以把兔子stop
  17. tortoise.calltoback = letOneStop2;
  18. // 开始跑
  19. tortoise.start();
  20. rabbit.start();
  21. }
  22. }

线程示例总结

(1)代码块锁是一个防止数据发生错误的一个重要手段;
(2)对象的统一性是非常重要的,这要想到对象的传入问题,要操作的对象只能new一次,其他的操作都是对这个传入的对象进行的,才能保证数据一致性,完整性和正确性。