java学习多线程之卖票示例
2013-10-20 14:04
330 查看
这一节我们来说一个示例就是卖票示例:
需求:
我们现在有100张票,然后分四个窗口来卖,直到卖完为止。
思路:
1、先定一个一个票类,描述票的属性,还有打印卖出的票,并且实现Runnable中的run方法。
2、定义一个主方法,把这个类当成一个独立的运行程序。
3、在主方法当中创建4个线程来卖票。
代码:
我们写完之后,在不是很慢的电脑上运行都是正常的,但是我们的这个程序总体上安全么?如果在if(num>0)这个地方线程一刚要执行的时候被切换出去了那么num此时如果恰巧是1的话,那么此时线程二进来后1>0之后就直接打印1,但是在线程一苏醒之后,这时候他不再判断num是否大于零而是直接打印了 num--这个时候就出现了0甚至是负数。这就是多线程当中出现的问题,那么如何解决这个问题。我们可以试想一下,如果在线程一退出的时候,能够让num不让其他对象访问,直到线程一苏醒之后处理完num之后,再让出num的控制权的话,这样是不是很安全呢,这个也叫做多线程当中的同步。同步是指,在同时有多个线程运行的时候,其中有一段代码块一个时候只能允许一个线程来处理,只有这个线程处理完了之后,其他的线程才有机会重新掌管这个代码块,周而复始。
java为了能够让我们处理上述的不同步问题就是一个线程执行的同时,其中共享的资源分别被其他的线程来执行着,这样就可能造成输出了不该输出的语句。为我们提供了一个关键字叫做synchronized。这个关键词的使用方法,是指定一个锁,来访问其内部的代码块。如果一个线程要处理访问其中的代码块的话,必须先拿到锁。并且这个锁要是所有的线程公用的锁才好,这样才能够起到锁的作用。当一个线程拿到锁之后,其他线程来访问的话如果没有锁,则一直判断另一个线程的锁是否释放,只有持有锁的线程把任务执行完之后,才会释放锁。这个锁一释放之后,其他的线程就有机会持有这个锁,然后进行任务的操作。这样就在多线程的情况下,保证了在某一个时刻,只能由一个线程来执行这段同步代码块。也保证了共享数据的安全性,不至于这段数据在被修改之后,其他线程仍然认为这个数据就是之前的按个数据的问题。究竟如何使用呢,代码如下:
其中同步代码块还有一种简写的形式,也就是说把代码块关键字synchronized( lock ){},把synchronized直接放到函数上,这样整个函数就是同步的了。也就是:
synchronized这个关键字加到代码块之前就是同步代码块,加到函数上面就是同步函数。
需求:
我们现在有100张票,然后分四个窗口来卖,直到卖完为止。
思路:
1、先定一个一个票类,描述票的属性,还有打印卖出的票,并且实现Runnable中的run方法。
2、定义一个主方法,把这个类当成一个独立的运行程序。
3、在主方法当中创建4个线程来卖票。
代码:
class Ticket implements Runnable { int num = 100; public void sellT() { while(true) { if(num>0) System.out.println(num--); } } public void run() { sellT(); } } class ThreadTickets { public static void main(String[] args) { Ticket p = new Ticket(); Thread t1 = new Thread(p); Thread t2 = new Thread(p); Thread t3 = new Thread(p); t1.start(); t2.start(); t3.start(); } }
我们写完之后,在不是很慢的电脑上运行都是正常的,但是我们的这个程序总体上安全么?如果在if(num>0)这个地方线程一刚要执行的时候被切换出去了那么num此时如果恰巧是1的话,那么此时线程二进来后1>0之后就直接打印1,但是在线程一苏醒之后,这时候他不再判断num是否大于零而是直接打印了 num--这个时候就出现了0甚至是负数。这就是多线程当中出现的问题,那么如何解决这个问题。我们可以试想一下,如果在线程一退出的时候,能够让num不让其他对象访问,直到线程一苏醒之后处理完num之后,再让出num的控制权的话,这样是不是很安全呢,这个也叫做多线程当中的同步。同步是指,在同时有多个线程运行的时候,其中有一段代码块一个时候只能允许一个线程来处理,只有这个线程处理完了之后,其他的线程才有机会重新掌管这个代码块,周而复始。
java为了能够让我们处理上述的不同步问题就是一个线程执行的同时,其中共享的资源分别被其他的线程来执行着,这样就可能造成输出了不该输出的语句。为我们提供了一个关键字叫做synchronized。这个关键词的使用方法,是指定一个锁,来访问其内部的代码块。如果一个线程要处理访问其中的代码块的话,必须先拿到锁。并且这个锁要是所有的线程公用的锁才好,这样才能够起到锁的作用。当一个线程拿到锁之后,其他线程来访问的话如果没有锁,则一直判断另一个线程的锁是否释放,只有持有锁的线程把任务执行完之后,才会释放锁。这个锁一释放之后,其他的线程就有机会持有这个锁,然后进行任务的操作。这样就在多线程的情况下,保证了在某一个时刻,只能由一个线程来执行这段同步代码块。也保证了共享数据的安全性,不至于这段数据在被修改之后,其他线程仍然认为这个数据就是之前的按个数据的问题。究竟如何使用呢,代码如下:
class Ticket implements Runnable { int num = 100; Object obj = new Object(); public void sellT() { while(true) { synchronized (obj) { if(num>0) { try { Thread.sleep(10); }catch(InterruptedException e) { } System.out.println("The CurrentThread is:"+Thread.currentThread().getName()+"The num is:"+num--); } } } } public void run() { sellT(); } } class ThreadTickets { public static void main(String[] args) { Ticket p = new Ticket(); Thread t1 = new Thread(p); Thread t2 = new Thread(p); Thread t3 = new Thread(p); t1.start(); t2.start(); t3.start(); } }
其中同步代码块还有一种简写的形式,也就是说把代码块关键字synchronized( lock ){},把synchronized直接放到函数上,这样整个函数就是同步的了。也就是:
class Ticket implements Runnable { int num = 100; Object obj = new Object(); public void sellT() { while(true) { try { Thread.sleep(100); }catch(InterruptedException e) { } pTicket(); } } public synchronized void pTicket() { if(num>0) { System.out.println("The CurrentThread is:"+Thread.currentThread().getName()+"The num is:"+num--); } } public void run() { sellT(); } } class ThreadTickets { public static void main(String[] args) { Ticket p = new Ticket(); Thread t1 = new Thread(p); Thread t2 = new Thread(p); Thread t3 = new Thread(p); t1.start(); t2.start(); t3.start(); } }
synchronized这个关键字加到代码块之前就是同步代码块,加到函数上面就是同步函数。
相关文章推荐
- JVM学习序列之一:Java Class文件结构分析
- 黑马程序员-JAVA学习之环境搭配
- 我的Java开发学习之旅------>求N内所有的素数
- Java学习笔记-------路径分隔符
- java基础学习总结——流
- java学习之路之web知识总结
- JAVA数组学习之一:对一维数组进行逆序排列
- Java基础学习之关键字
- 你真的适合学习JAVA开发吗?——献给那些想走进JAVA的人
- JVM学习之一----基本Java语句翻译
- Java基础学习03 -- 运算符与流程控制语句
- Java8学习计划--关于多核多线程并发编程-Java8-CompletableFuture 1的介绍
- Java构造方法学习
- 黑马程序员-------学习日记Java基础 第一天
- 转载 Java学习之路 --The Road Of Java Study
- 黑马程序员——黑马学习日志之二十二 Java高新技术(四)
- Java编程思想学习心得(三)基本类型
- java学习笔记(二)流
- 学习笔记之--java容器
- 一位资深程序员大牛给予Java初学者的学习建议