1. package Test22_Demo.Demo07;/*
    2. @create 2020--12--15--10:32
    3. */
    4. /**
    5. * 使用第二种方式创建线程,原因是执行线程目标对象共享
    6. * 顶一个卖票的线程执行目标对象 - 加锁
    7. *
    8. * 演示synchronized可以修饰方法,被修饰的方法叫做同步方法
    9. * 同时也支持修饰静态方法!!!,但是一旦修饰了静态方法以后,这个对象就不是this了
    10. *
    11. * 静态对象锁
    12. *
    13. * 当前案例中,我们使用对象锁对当前的这个Ticket加锁,目的是this是当前正在被调用的这个Ticket对象
    14. * 不管是synchronized代码块中,还是封装的一个synchronized方法,都可以保证使用的是同一个锁对象
    15. *
    16. */
    17. public class Ticket implements Runnable {
    18. //票数 - 静态方法不能调用非静态资源
    19. private static int number = 100;
    20. //生命成员变量为定义锁对象
    21. private Object lock = new Object();
    22. //创建一个标记,让不同的人来执行不同的代码块
    23. private int x = 0;
    24. @Override
    25. public void run() {
    26. while (true) {
    27. //进行取余的运算,模拟买票的人
    28. if (x % 2 == 0) {
    29. //把当前这个被调用的对象给锁住
    30. synchronized (Ticket.class) {
    31. //线程暂停
    32. try {
    33. Thread.sleep(500);
    34. } catch (InterruptedException e) {
    35. e.printStackTrace();
    36. }
    37. //如果有票就卖
    38. if (number > 0) {
    39. String threadName = Thread.currentThread().getName();
    40. System.out.println(threadName + "正在销售第"+(number--) + "张票");
    41. }
    42. }
    43. } else {
    44. //调用sell方法 - 静态同步方法
    45. //sell();
    46. Ticket.sell();
    47. }
    48. //当票数等于0,就表示没有票了
    49. if (number <= 0) {
    50. break;
    51. }
    52. x++;//为了改变x的值,从而继续对2进行取余
    53. }
    54. }
    55. //封装一个方法,用于定义同步买票 - 同步方法
    56. public static synchronized void sell() {
    57. //需要加锁的逻辑放到一个方法中
    58. try {
    59. Thread.sleep(20);
    60. } catch (InterruptedException e) {
    61. e.printStackTrace();
    62. }
    63. //有票就卖
    64. if (number > 0) {
    65. String threadName = Thread.currentThread().getName();
    66. System.out.println(threadName + "正在销售第"+(number--) + "张票");
    67. }
    68. }
    69. }
    1. package Test22_Demo.Demo07;/*
    2. @create 2020--12--15--10:44
    3. */
    4. /**
    5. * 测试线程
    6. */
    7. public class ThreadDemo {
    8. public static void main(String[] args) {
    9. //实例化目标
    10. Ticket ticket = new Ticket();
    11. //使用该买票的目标创建多个程序
    12. Thread thread1 = new Thread(ticket, "Jack");
    13. Thread thread2 = new Thread(ticket, "Rose");
    14. Thread thread3 = new Thread(ticket, "Tom");
    15. //启动多个线程
    16. thread1.start();
    17. thread2.start();
    18. thread3.start();
    19. }
    20. }