• java学习多线程之卖票示例


    这一节我们来说一个示例就是卖票示例:

    需求:

    我们现在有100张票,然后分四个窗口来卖,直到卖完为止。

    思路:

    1、先定一个一个票类,描述票的属性,还有打印卖出的票,并且实现Runnable中的run方法。

    2、定义一个主方法,把这个类当成一个独立的运行程序。

    3、在主方法当中创建4个线程来卖票。

    代码:

     1 class Ticket implements Runnable
     2 {
     3 
     4     int num = 100;
     5 
     6     public void sellT()
     7     {
     8 
     9         while(true)
    10         {
    11 
    12             if(num>0)
    13                 System.out.println(num--);
    14 
    15         }
    16 
    17     }
    18 
    19     public void run()
    20     {
    21 
    22         sellT();
    23 
    24     }
    25 
    26 }
    27 
    28 class ThreadTickets
    29 {
    30 
    31     public static void main(String[] args) {
    32         
    33         Ticket p = new Ticket();
    34 
    35         Thread t1 = new Thread(p);
    36         Thread t2 = new Thread(p);
    37         Thread t3 = new Thread(p);
    38 
    39         t1.start();
    40         t2.start();
    41         t3.start();
    42 
    43     }
    44 
    45 }

    我们写完之后,在不是很慢的电脑上运行都是正常的,但是我们的这个程序总体上安全么?如果在if(num>0)这个地方线程一刚要执行的时候被切换出去了那么num此时如果恰巧是1的话,那么此时线程二进来后1>0之后就直接打印1,但是在线程一苏醒之后,这时候他不再判断num是否大于零而是直接打印了 num--这个时候就出现了0甚至是负数。这就是多线程当中出现的问题,那么如何解决这个问题。我们可以试想一下,如果在线程一退出的时候,能够让num不让其他对象访问,直到线程一苏醒之后处理完num之后,再让出num的控制权的话,这样是不是很安全呢,这个也叫做多线程当中的同步。同步是指,在同时有多个线程运行的时候,其中有一段代码块一个时候只能允许一个线程来处理,只有这个线程处理完了之后,其他的线程才有机会重新掌管这个代码块,周而复始。

    java为了能够让我们处理上述的不同步问题就是一个线程执行的同时,其中共享的资源分别被其他的线程来执行着,这样就可能造成输出了不该输出的语句。为我们提供了一个关键字叫做synchronized。这个关键词的使用方法,是指定一个锁,来访问其内部的代码块。如果一个线程要处理访问其中的代码块的话,必须先拿到锁。并且这个锁要是所有的线程公用的锁才好,这样才能够起到锁的作用。当一个线程拿到锁之后,其他线程来访问的话如果没有锁,则一直判断另一个线程的锁是否释放,只有持有锁的线程把任务执行完之后,才会释放锁。这个锁一释放之后,其他的线程就有机会持有这个锁,然后进行任务的操作。这样就在多线程的情况下,保证了在某一个时刻,只能由一个线程来执行这段同步代码块。也保证了共享数据的安全性,不至于这段数据在被修改之后,其他线程仍然认为这个数据就是之前的按个数据的问题。究竟如何使用呢,代码如下:

     1 class Ticket implements Runnable
     2 {
     3 
     4     int num = 100;
     5 
     6     Object obj = new Object();
     7 
     8     public void sellT()
     9     {
    10 
    11         while(true)
    12         {
    13             synchronized (obj)
    14             {
    15 
    16                 if(num>0)
    17                 {
    18                     try
    19                     {
    20 
    21                         Thread.sleep(10);
    22 
    23                     }catch(InterruptedException e)
    24                     {
    25 
    26 
    27                     }
    28                     System.out.println("The CurrentThread is:"+Thread.currentThread().getName()+"The num is:"+num--);
    29 
    30                 }        
    31 
    32             }
    33         }
    34 
    35     }
    36 
    37     public void run()
    38     {
    39 
    40         sellT();
    41 
    42     }
    43 
    44 }
    45 
    46 class ThreadTickets
    47 {
    48 
    49     public static void main(String[] args) {
    50         
    51         Ticket p = new Ticket();
    52 
    53         Thread t1 = new Thread(p);
    54         Thread t2 = new Thread(p);
    55         Thread t3 = new Thread(p);
    56 
    57         t1.start();
    58         t2.start();
    59         t3.start();
    60 
    61     }
    62 
    63 }

    其中同步代码块还有一种简写的形式,也就是说把代码块关键字synchronized( lock ){},把synchronized直接放到函数上,这样整个函数就是同步的了。也就是:

     1 class Ticket implements Runnable
     2 {
     3 
     4     int num = 100;
     5 
     6     Object obj = new Object();
     7 
     8     public void sellT()
     9     {
    10 
    11         while(true)
    12         {
    13             try
    14             {
    15 
    16             Thread.sleep(100);
    17 
    18             }catch(InterruptedException e)
    19             {
    20 
    21 
    22             }
    23             pTicket();        
    24             
    25         }
    26 
    27     }
    28 
    29     public synchronized  void pTicket()
    30     {
    31 
    32         if(num>0)
    33         {
    34 
    35             System.out.println("The CurrentThread is:"+Thread.currentThread().getName()+"The num is:"+num--);
    36 
    37         }
    38 
    39     }
    40 
    41     public void run()
    42     {
    43 
    44         sellT();
    45 
    46     }
    47 
    48 }
    49 
    50 class ThreadTickets
    51 {
    52 
    53     public static void main(String[] args) {
    54         
    55         Ticket p = new Ticket();
    56 
    57         Thread t1 = new Thread(p);
    58         Thread t2 = new Thread(p);
    59         Thread t3 = new Thread(p);
    60 
    61         t1.start();
    62         t2.start();
    63         t3.start();
    64 
    65     }
    66 
    67 }

    synchronized这个关键字加到代码块之前就是同步代码块,加到函数上面就是同步函数。

  • 相关阅读:
    提示35. 怎样实现OfTypeOnly<TEntity>()这样的写法
    (翻译)Entity Framework技巧系列之十
    Entity Framework教程(第二版)
    实战 ASP.NET Web API
    Apache,PHP,MySQL的安装,配置
    Apache配置虚拟目录和多主机头
    web.config配置详细说明
    百度UEditor编辑器使用教程与使用方法
    若要调试此模块,请将其项目生成配置更改为“调试”模式。若要取消显示此消息,请禁用“启动时若没有用户代码则发出警告”调试器选项
    jquery筛选器
  • 原文地址:https://www.cnblogs.com/sunchuanzhen/p/3379026.html
Copyright © 2020-2023  润新知