java多线程模拟实现售票功能

铁道部发布了一个售票任务,要求销售1000张票,要求有3个窗口来进行销售,请编写多线程程序来模拟这个效果。

1 线程类

测试方法:

public static void main(String[] args) {
    MyThread t1 = new MyThread("窗口1");
    MyThread t2 = new MyThread("窗口1");
    MyThread t3 = new MyThread("窗口1");

    t1.start();
    t2.start();
    t3.start();

}

1.1 局部加锁

public class MyThread extends Thread{

 private static int ticket = 1000;
 private static Object obj = new Object();

 public MyThread(String name) {
  super(name);
 }

 @Override
 public void run() {

  while(ticket > 0){
   synchronized(obj){
    if(ticket > 0){
     System.out.println(Thread.currentThread().getName() + "正在销售第" +(1001-ticket)+ "张票");
     ticket--;
    }
    if(ticket <= 0){
     System.out.println(Thread.currentThread().getName() + "票已售罄");
    }
   }
  }
 }
}

1.2 方法加锁

public class MyThread extends Thread{

 private static int ticket = 1000;

 public MyThread(String name) {
  super(name);
 }

 @Override
 public void run() {

  while(ticket > 0){
   method02();
  }
 }

 //锁对象:类的字节码文件对象(MyThread.class),有static修饰
 public static synchronized void method02(){
  if(ticket > 0){
   System.out.println(Thread.currentThread().getName() + "正在销售第" +(1001-ticket)+ "张票");
   ticket--;
  }
  if(ticket <= 0){
   System.out.println(Thread.currentThread().getName() + "票已售完");
  }
 }
}

1.3 手动加锁

public class MyThread extends Thread{

 private static int ticket = 1000;
 private static Lock lock = new ReentrantLock();

 public MyThread(String name) {
  super(name);
 }

 @Override
 public void run() {

  while(ticket > 0){
   lock.lock();//手动上锁
   if(ticket > 0){
    System.out.println(Thread.currentThread().getName() + "正在销售第" +(1001-ticket)+ "张票");
    ticket--;
   }
   if(ticket <= 0){
    System.out.println(Thread.currentThread().getName() + "票已售完");
   }
   lock.unlock();//手动解锁
  }
 }
}

2 任务类

测试方法:

public static void main(String[] args) {
    Task task = new Task();
    Thread t1 = new Thread(task, "窗口1");
    Thread t2 = new Thread(task, "窗口2");
    Thread t3 = new Thread(task, "窗口3");
    t1.start();
    t2.start();
    t3.start();

}

2.1 局部加锁

public class Task implements Runnable{
 private int tickets=1000;

 @Override
 public void run() {
  while(tickets>0){
   synchronized (this) {
    if(tickets > 0)
             {
                 System.out.printf ("%s窗口正在售出第%d张票\n",Thread.currentThread().getName(),1001-tickets);
                 tickets--;
             }
             if(tickets<=0){
              System.out.printf("%s窗口售罄\n",Thread.currentThread().getName());
             }
   }

  }
 }
}

2.2 方法加锁

public class Task implements Runnable{
 private int tickets=1000;

 @Override
 public void run() {
  while(tickets>0){
   method();
  }
 }
    //方法加锁,没有使用static修饰
 public synchronized void method(){
  if(tickets > 0)
        {
            System.out.printf ("%s窗口正在售出第%d张票\n",Thread.currentThread().getName(),1001-tickets);
            tickets--;
        }
        if(tickets<=0){
         System.out.printf("%s窗口售罄\n",Thread.currentThread().getName());
        }
 }
}

2.3 手动加锁

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Task implements Runnable{
 private int tickets=1000;
 private Lock lock =new  ReentrantLock();
 @Override
 public void run() {
  while(tickets>0){
   lock.lock();//手动上锁
   if(tickets > 0)
            {
                System.out.printf ("%s窗口正在售出第%d张票\n",Thread.currentThread().getName(),1001-tickets);
                tickets--;
            }
            if(tickets<=0){
             System.out.printf("%s窗口售罄\n",Thread.currentThread().getName());
            }
            lock.unlock();//手动关锁
  }
 }
}

效果截图:

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Java面试题冲刺第二十五天--实战编程2

    目录 面试题2:怎么理解负载均衡的?你处理负载均衡都有哪些途径? 1.[协议层]http重定向 2.[协议层]DNS轮询 3.[协议层]CDN 4.[协议层]反向代理负载均衡 5.[网络层]IP负载均衡 面试题3:你平时是怎样定位线上问题的? 总结 面试题1:当你发现一条SQL很慢,你的处理思路是什么? 发现Bug 确定Bug不是自己造成的,如果无法确定,不要理会步骤1 向组内宣传"程序里有一个未知Bug,错不在我" 谁响应,谁对Bug负责 没人响应,就要求特定人员配合调试 如果不配合

  • Java 动态数组的实现示例

    目录 静态数组 动态数组的实现原理 1.添加元素 2.删除元素 3.数组扩容 4.数组缩减 静态数组 Java中最基本的数组大家肯定不会陌生: int[] array = new int[6]; for (int i = 0; i < array.length; i++){ array[i] = 2 * i + 1; } 通过循环把元素放入指定的位置中,类似于这样: 这是一个静态数组,因为我们在第一步初始化的时候就已经固定了它的长度,后面再也无法改变.所以,由于有这个限制,静态数组不适用于那些不

  • Java面试题冲刺第二十六天--实战编程

    目录 面试题1:你们是怎样保存用户密码等敏感数据的? 面试题2:怎么控制用户请求的幂等性的? 1.设置唯一索引:防止新增脏数据 2.token机制:防止页面重复提交 3.悲观锁 4.乐观锁 5.分布式锁 面试题3:你们是如何预防SQL注入问题的? 预防方式: 1.PreparedStatement(简单有效) 2.使用正则表达式过滤传入的参数 3.使用正则表达式过滤传入的URL 总结 面试题1:你们是怎样保存用户密码等敏感数据的? 本题回答参考朱晔的<Java业务开发常见错误100例> 我们知

  • Java实现递归计算n的阶乘

    本文实例为大家分享了Java实现递归计算n的阶乘的具体代码,供大家参考,具体内容如下 问题描述 利用递归的思想实现阶乘的计算,以 n!为例 (一).n的范围 1.n<0:n!无意义 2.n=0或n=1:n!=1 3.n>2:n!=n(n-1)! 关于 0!=1 的一个合理性解释: 根据阶乘的定义n!=n(n-1)!, 可变形为n=(n+1)!/(n+1), 带入有0=1!/1=1 (二).问题分析 1.n<0时提醒用户输入有误 (1)在未知循环次数时,可以采用while语句来提醒 (2)

  • java synchronized 锁机制原理详解

    目录 前言: 1.synchronized 的作用: 2.synchronized 底层语义原理: 3. synchronized 的显式同步与隐式同步: 3.1.synchronized 代码块底层原理: 3.2.synchronized 方法底层原理: 4.JVM 对 synchronized 锁的优化: 4.1.锁升级:偏向锁->轻量级锁->自旋锁->重量级锁 4.1.1.synchronized 的 Mark word 标志位: 4.1.2.锁升级过程: 4.2.锁消除: 4.3

  • Java CharacterEncodingFilter过滤器的理解和配置案例详解

    在web项目中我们经常会遇到当前台JSP页面和JAVA代码中使用了不同的字符集进行编码的时候就会出现表单提交的数据或者上传/下载中文名称文件出现乱码的问题,这些问题的原因就是因为我们项目中使用的编码不一样.为了解决这个问题我们就可以使用CharacterEncodingFilter类,他是Spring框架对字符编码的处理,基于函数回调,对所有请求起作用,只在容器初始化时调用一次,依赖于servlet容器.具体配置如下: <filter> <filter-name>character

  • java实现多客户聊天功能

    java 实现多客户端聊天(TCP),供大家参考,具体内容如下 1. 编程思想: 1).要想实现多客户端聊天,首先需要有多个客户端,而这些客户端需要随时发送消息和接受消息,所以收发消息需要放入不同的线程中. 2).多客户聊天并不是多个客户之间进行两两通信,而是需要所有客户端与服务端进行交互,再由服务端统一下发信息到其他参与聊天的客户端. 2. 代码实现: 2.1 实现专用于接收消息的子线程ReceiveThread 将接收消息和发送消息分为两个线程,其中将发送消息写入主线程中,开启新的线程用于接

  • Java中的equsals和==

    目录 Java的equsals和== 1.Java 中的== 2.Java 中equals方法 Java的equsals和== 前言:在我们常用的类中equals被重写后,作用就是为了比较对象的内容,==是比较对象的内存地址.但并不能说所有的equals方法就是比较对象的内容. 1.Java 中的== 1).对于对象引用类型:"=="比较的是对象的内存地址. 比如说: String s1 = "Hello"; String s2 = new String (&quo

  • Java面试题冲刺第二十五天--并发编程3

    目录 面试题1:你了解线程池么?简单介绍一下. 追问1:连接池 和 线程池是一个意思么?有什么区别? 不同点 面试题2:线程池中核心线程数量大小你是怎么设置的? 追问1:核心线程数量过大或过小会造成什么后果? 面试题3:线程池都有哪些状态呀? 追问1:什么条件下会进入TERMINATED状态 总结 面试题1:你了解线程池么?简单介绍一下. java提供的一个java.util.concurrent.Executor接口的实现用于创建线程池. 线程池是一种多线程处理形式,处理过程中将任务提交到线程

  • Java DatabaseMetaData用法案例详解

    目录 一 . 得到这个对象的实例 二. 方法getTables的用法 三. 方法getColumns的用法 四.方法getPrimaryKeys的用法 五.方法.getTypeInfo()的用法 六.方法getExportedKeys的用法 一 . 得到这个对象的实例 Connection con ; con = DriverManager.getConnection(url,userName,password); DatabaseMetaData dbmd = con.getMetaData(

随机推荐