多线程---使用synchronized---多窗口出售火车票
2021/12/31 23:43:00
本文主要是介绍多线程---使用synchronized---多窗口出售火车票,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!
package com.ldp.demo.Thread; public class Ticket_Synchronized { public static void main(String[] args) { Ticket_tation ticket = new Ticket_tation(); new Thread(ticket, "a") { }.start(); new Thread(ticket, "b") { }.start(); new Thread(ticket, "c") { }.start(); new Thread(ticket, "d") { }.start(); } } class Ticket_tation implements Runnable { private int ticketNum = 10; @Override public void run() { while (ticketNum > 0) { //while和synchronized 的位置不能互换, synchronized (this) { //要不然票会一直是同一个窗口出票 //synchronized 在这里锁的是对象 if (ticketNum==0){ System.out.println( Thread.currentThread().getName()+"出票失败,"+"票已售完!" ); return; } try { Thread.sleep(50);//睡眠50毫秒,要不然执行太快,会是同一个窗口出票 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println((ticketNum--) + "号票已售出!" + Thread.currentThread().getName()); } } } }
结果
10号票已售出!a
9号票已售出!d
8号票已售出!d
7号票已售出!c
6号票已售出!b
5号票已售出!b
4号票已售出!c
3号票已售出!c
2号票已售出!c
1号票已售出!d
a出票失败,票已售完!
c出票失败,票已售完!
b出票失败,票已售完!
这种方式效率太低,因为synchronized(this)锁住的是对象,代码块里所有的内容都被阻塞了,耗费时间,可以改为锁具体操作,即锁扣除票数方法substract_ticket();
package com.ldp.demo.Thread; public class Ticket_Synchronized { public static void main(String[] args) { Ticket_tation ticket = new Ticket_tation(); new Thread(ticket, "a") { }.start(); new Thread(ticket, "b") { }.start(); new Thread(ticket, "c") { }.start(); new Thread(ticket, "d") { }.start(); } } class Ticket_tation implements Runnable { private int ticketNum = 3; public synchronized Result substract_ticket() { if (ticketNum == 0) { return new Result(false, ticketNum); } return new Result(true, ticketNum--); } @Override public void run() { while (ticketNum > 0) { if (ticketNum == 0) { System.out.println(Thread.currentThread().getName() + "出票失败," + "票已售完!"); return; } try { Thread.sleep(500); } catch (InterruptedException e) { e.printStackTrace(); } Result result = substract_ticket(); if (!result.isFlag()) { System.out.println(Thread.currentThread().getName() + "出票失败," + "票已售完!"); return; } System.out.println(result.getCount() + "号票已售出!" + Thread.currentThread().getName()); } } } class Result { boolean flag; int count; public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } public Result() { } public Result(boolean flag, int count) { this.flag = flag; this.count = count; } }
3号票已售出!a
2号票已售出!d
b出票失败,票已售完!
1号票已售出!c
a出票失败,票已售完!
synchronized锁的是非静态方法也叫对象锁。
多个线程调用同一个对象的同步方法会阻塞,调用不同对象的同步方法不会阻塞。(java对象的内存地址是否相同)
synchronized修饰静态的方法也叫类锁
1,要满足方法同步(或者代码块同步)就必须保证多线程访问的是同一个对象(在java内存中的地址是否相同)。
2,类锁和对象锁同时存在时,多线程访问时不会阻塞,因为他们不是一个锁。
假如有两个火车站,每个火车站有两个窗口售票,那就不能锁对象了,要锁具体操作的方法了。
package com.ldp.demo.Thread; import org.apache.commons.lang3.time.StopWatch; /** * 多个火车站多个窗口售票 */ public class ThreadTicket { private static final int NUM = 7; public static int getNum() { return NUM; } public static void main(String[] args) { Ticket.getTicket().setTicketNum(NUM); TicketStation station1 = new TicketStation("南火车站"); TicketStation station2 = new TicketStation("西火车站"); new Thread(station1, "西窗口一").start(); new Thread(station2, "南窗口二").start(); new Thread(station2, "西窗口一").start(); new Thread(station1, "南窗口二").start(); } } class Ticket { private static final Ticket ticket = new Ticket(); public Ticket() { } public static Ticket getTicket() { return ticket; } private int TicketNum; public int getTicketNum() { return TicketNum; } public void setTicketNum(int ticketNum) { this.TicketNum = ticketNum; } public synchronized Result substratTicket() { Result result = new Result(); if (TicketNum == 0) { result.setFlag(false); result.setCount(TicketNum); } else { result.setFlag(true); result.setCount(TicketNum); --TicketNum; } return result; } } class TicketStation implements Runnable { private String name; public String getName() { return name; } public TicketStation() { } public TicketStation(String name) { this.name = name; } @Override public void run() { while (Ticket.getTicket().getTicketNum() > 0) { if (Ticket.getTicket().getTicketNum() == 0) { break; } try { Thread.sleep(5); } catch (InterruptedException e) { e.printStackTrace(); } Result result = Ticket.getTicket().substratTicket(); if (result.isFlag()) { Out.getInstance().write(System.currentTimeMillis(), this, Thread.currentThread().getName(), result.getCount()); } else { System.out.println(System.currentTimeMillis() + this.name + Thread.currentThread().getName() + "出票失败"); } } } } class Result { boolean flag; int count; public boolean isFlag() { return flag; } public void setFlag(boolean flag) { this.flag = flag; } public int getCount() { return count; } public void setCount(int count) { this.count = count; } public Result() { } public Result(boolean flag, int count) { this.flag = flag; this.count = count; } }
package com.ldp.demo.Thread; class Out{ private final static Out out=new Out(); private Out(){} public static Out getInstance(){ return out; } static void write(long time,TicketStation station,String adress,int count){ System.out.println(time+ station.getName()+"在"+adress+"卖出了第"+(ThreadTicket.getNum()-count+1)+"票"); } }
这篇关于多线程---使用synchronized---多窗口出售火车票的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!
- 2024-11-23增量更新怎么做?-icode9专业技术文章分享
- 2024-11-23压缩包加密方案有哪些?-icode9专业技术文章分享
- 2024-11-23用shell怎么写一个开机时自动同步远程仓库的代码?-icode9专业技术文章分享
- 2024-11-23webman可以同步自己的仓库吗?-icode9专业技术文章分享
- 2024-11-23在 Webman 中怎么判断是否有某命令进程正在运行?-icode9专业技术文章分享
- 2024-11-23如何重置new Swiper?-icode9专业技术文章分享
- 2024-11-23oss直传有什么好处?-icode9专业技术文章分享
- 2024-11-23如何将oss直传封装成一个组件在其他页面调用时都可以使用?-icode9专业技术文章分享
- 2024-11-23怎么使用laravel 11在代码里获取路由列表?-icode9专业技术文章分享
- 2024-11-22怎么实现ansible playbook 备份代码中命名包含时间戳功能?-icode9专业技术文章分享