zoukankan      html  css  js  c++  java
  • java 多线程之synchronized wait/notify解决买票问题

    一.Java线程具有五中基本状态

    新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();

    就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;

    运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就     绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;

    阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:

    1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;

    2.同步阻塞 -- 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;

    3.其他阻塞 -- 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。

    死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。

    二. Java多线程的创建及启动

    1.继承Thread类,重写该类的run()方法。

    两个线程同时运行,随机产生4位随机字符

     1 import java.util.Random;
     2 
     3 public class 多线程 {
     4 
     5     public static Object lock = new Object();
     6 
     7     public static void randomString() {
     8         String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
     9         Random random = new Random();
    10         StringBuffer sb = new StringBuffer();
    11         for (int i = 0; i < 4; i++) {
    12             int number = random.nextInt(62);
    13             sb.append(str.charAt(number));
    14         }
    15         System.out.print(sb);
    16     }
    17 
    18     public static void main(String[] args) {
    19 
    20         new Thread(new myTh1()).start();
    21         new Thread(new myTh2()).start();
    22 
    23     }
    24 
    25 }
    26 
    27 class myTh1 extends Thread {
    28     @Override
    29     public void run() {
    30         while (true) {
    31 
    32             try {
    33                 synchronized (多线程.lock) {
    34                     多线程.randomString();
    35                     System.out.print("------"+Thread.currentThread().getName());
    36                     System.out.println();
    37                 }
    38                 sleep(1000);        
    39             } catch (InterruptedException e) {
    40                 e.printStackTrace();
    41             }
    42         }
    43     }
    44 }
    45 
    46 class myTh2 extends Thread {
    47     @Override
    48     public void run() {
    49         while (true) {
    50             try {
    51                 synchronized (多线程.lock) {
    52                     多线程.randomString();
    53                     System.out.print("------"+Thread.currentThread().getName());
    54                     System.out.println();
    55                 }
    56                 sleep(1000);
    57             } catch (InterruptedException e) {
    58                 e.printStackTrace();
    59             }
    60         }
    61     }
    62 }
    View Code

    2.实现Runnable接口,并重写该接口的run()方法,该run()方法同样是线程执行体,创建Runnable实现类的实例,并以此实例作为Thread类的target来创建Thread对象,该Thread对象才是真正的线程对象

    主线程和两个实现Runnable接口的线程同时运行,线程对象只运行5次。

     1 public class 多线程Runnable {
     2 
     3     public static void main(String[] args) {
     4         System.out.println(Thread.currentThread().getName());
     5         try {
     6             Thread.sleep(3000);
     7         } catch (InterruptedException e) {
     8             e.printStackTrace();
     9         }
    10         
    11         new Thread(new myTh3()).start();
    12         new Thread(new myTh4()).start();
    13             
    14 
    15     }
    16 }
    17     class myTh3 extends Thread{
    18         int i=0;
    19         @Override
    20         public void run() {
    21             while (i<5) {
    22                 System.out.println(Thread.currentThread().getName());
    23                 try {
    24                     sleep(2000);
    25                 } catch (InterruptedException e) {    
    26                     e.printStackTrace();
    27                 }
    28                 i++;
    29             }
    30             
    31         }
    32 
    33     }
    34     
    35     class myTh4 implements Runnable{
    36 
    37         int i=0;
    38         @Override
    39         public void run() {
    40             while (i<5) {
    41                 System.out.println(Thread.currentThread().getName());
    42                 i++;
    43             }
    44         
    45     }
    46 }
    View Code

    3.synchronized, wait, notify结合:

    解决问题三个人去买票,张某有20元,李某10元。赵某5元。电影票5元一张,售货员只有3张5元的

      1 /*问题:
      2  * 三个人去买票,张某有20元,李某10元。赵某5元。
      3  * 电影票5元一张,售货员只有3张5元的。
      4  * 
      5  * 思路:
      6  * 张某买了票就会少3张5元的
      7  * 李某买了票就会少1张5元的
      8  * 赵某买了票就会多1张5元的
      9  * 所以有三种情况:
     10  * 一。赵某先买,张李都可以买
     11  * 二。张某先买,此时李某买不了,只能等待赵某买了,再买
     12  * 三。李某先买,此时张某买不了,只能等待赵某买了,再买
     13  * 
     14  * 静态常量:售货员总钱数 sum=3
     15  * 
     16  *     1.创建三个线程分别为张某,李某,赵某
     17  *     2.判断此时sum值,合适就买票,减去相应的钱数,不合适就等待。
     18  */
     19 import java.util.ArrayList;
     20 import java.util.Iterator;
     21 import java.util.List;
     22 
     23 public class 多线程3 {
     24 
     25     public static int sum = 3;//设置零钱总张数为3张
     26     public static Object look = new Object();//建立一个锁
     27 
     28     public static List<Thread> arrayList = new ArrayList<>();//建立集合 保存这三个购买人的线程
     29 
     30     public static void main(String[] args) throws InterruptedException {
     31         //随机将赵某李某张某添加到集合中
     32         arrayList.add(new li());
     33         arrayList.add(new zhang());
     34         arrayList.add(new zhao());
     35 
     36         //通过迭代器遍历集合
     37         Iterator<Thread> iterator = arrayList.iterator();
     38 
     39         while (iterator.hasNext()) {
     40             //获取线程
     41             Thread t = iterator.next();
     42             //线程启动
     43             t.start();
     44             //线程睡眠
     45             t.sleep(2000);
     46         }
     47 
     48     }
     49 }
     50 /**
     51  * 张某线程
     52  * @author Administrator
     53  *
     54  */
     55 class zhang extends Thread {
     56     @Override
     57     public void run() {
     58         //因为要判断等待和唤醒,并且操作sum,所以在此处加锁
     59         synchronized (多线程3.look) {
     60             while (多线程3.sum < 3) {
     61                 try {
     62                     System.out.println("因为此时零钱不足:"+多线程3.sum+"张");
     63                     System.out.println("所以张某没买到电影票,等待购买");
     64                     多线程3.look.wait();
     65                 } catch (InterruptedException e) {
     66                     e.printStackTrace();
     67                 }
     68             }  if (多线程3.sum > 2) {
     69                 多线程3.sum = 多线程3.sum - 3;
     70                 多线程3.look.notify();
     71                 System.out.println("张某买到了电影票");
     72                 System.out.println("此时零钱数为:"+多线程3.sum+"张");
     73             }
     74         }
     75     }
     76 }
     77 /**
     78  * 李某线程
     79  * @author Administrator
     80  *
     81  */
     82 class li extends Thread {
     83     @Override
     84     public void run() {
     85         synchronized (多线程3.look) {
     86             while (多线程3.sum < 1) {
     87                 try {
     88                     System.out.println("因为此时零钱不足:"+多线程3.sum+"张");
     89                     System.out.println("所以李某没买到电影票,等待购买");
     90                     多线程3.look.wait();
     91                 } catch (InterruptedException e) {
     92                     e.printStackTrace();
     93                 }
     94             }  if (多线程3.sum >= 1) {
     95                 多线程3.sum = 多线程3.sum - 1;
     96                 多线程3.look.notify();
     97                 System.out.println("李某买到了电影票");
     98                 System.out.println("此时零钱数为:"+多线程3.sum+"张");
     99             }
    100 
    101         }
    102     }
    103 }
    104 /**
    105  * 赵某线程
    106  * @author Administrator
    107  *
    108  */
    109 class zhao extends Thread {
    110     @Override
    111     public void run() {
    112         synchronized (多线程3.look) {
    113             if (多线程3.sum >= 0) {
    114                 多线程3.sum = 多线程3.sum + 1;
    115                 System.out.println("赵某买到了电影票");
    116                 System.out.println("此时零钱数为:"+多线程3.sum+"张");
    117                 多线程3.look.notify();
    118             }
    119         }
    120     }
    121 }

    全部都是培训课后习题,最后一个足足搞了半天,希望我写的没毛病,求指教。。谢谢大佬。

  • 相关阅读:
    多态与多态性,鸭子类型
    类的继承与派生,抽象类
    常用模块
    模块与包
    三元表达式、列表推导式、生成器表达式、递归、匿名函数、内置函数
    函数装饰器
    函数基础
    文件处理
    数据类型
    Spring源码分析--IOC流程
  • 原文地址:https://www.cnblogs.com/LiuOOP/p/10997182.html
Copyright © 2011-2022 走看看