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

需求:

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

思路:

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

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

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

代码:

 class Ticket implements Runnable
{ int num = ; public void sellT()
{ while(true)
{ if(num>)
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 = ; Object obj = new Object(); public void sellT()
{ while(true)
{
synchronized (obj)
{ if(num>)
{
try
{ Thread.sleep(); }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 = ; Object obj = new Object(); public void sellT()
{ while(true)
{
try
{ Thread.sleep(); }catch(InterruptedException e)
{ }
pTicket(); } } public synchronized void pTicket()
{ if(num>)
{ 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这个关键字加到代码块之前就是同步代码块,加到函数上面就是同步函数。

java学习多线程之卖票示例的更多相关文章

  1. Java之多线程窗口卖票问题(Runnable)

    /** * 例子:创建三个窗口卖票,总票数为100张.使用实现Runnable接口的方式 * 存在线程的安全问题,待解决. */class Window1 implements Runnable{ p ...

  2. Java之多线程窗口卖票问题(Thread)

    /** * * 例子:创建三个窗口卖票,总票数为100张.使用继承Thread类的方式 * * 存在线程的安全问题,待解决. * */class Window extends Thread{ priv ...

  3. java多线程实现卖票小程序

    package shb.java.demo; /** * 多线程测试卖票小程序. * @Package:shb.java.demo * @Description: * @author shaobn * ...

  4. java 多线程之卖票两种方式

    1.通过extends Thread /* 需求:简单的卖票,多个窗口同时买票 (共用资源) 创建线程的第二种方式:实现Runnable接口 步骤: 1,定义类实现Runnable接口 2,覆盖/重写 ...

  5. Java学习多线程第二天

    内容介绍 线程安全 线程同步 死锁 Lock锁 等待唤醒机制 1    多线程 1.1     线程安全 如果有多个线程在同时运行,而这些线程可能会同时运行这段代码.程序每次运行结果和单线程运行的结果 ...

  6. java学习——多线程

    本文内容来源于  历经5年锤练--史上最适合初学者入门的Java基础视频 线程:就是进程中一个负责程序执行的控制单元(执行路径) 每一个线程都有自己运行的内容.这个内容可以称为线程要执行的任务. 多线 ...

  7. Java学习---多线程的学习

    基础知识 每个正在系统上运行的程序都是一个进程(process).每个进程包含一到多个线程(thread).进程也可能是整个程序或者是部分程序的动态执行. 线程是一组指令的集合,或者是程序的特殊段,它 ...

  8. Java学习多线程第一天

    内容介绍 Thread 线程创建 线程池 线程状态图 1 多线程 1.1     多线程介绍 学习多线程之前,我们先要了解几个关于多线程有关的概念. 进程:进程指正在运行的程序.确切的来说,当一个程序 ...

  9. java学习多线程之创建多线程一

    现在我们有这么一个需求,就是在主线程在运行的同时,我们想做其他的任务,这个时候我们就用到了多线程.那么如何创建多线程,我们知道在系统当中qq的多线程创建是由操作系统来完成的,那么如果我们想在java当 ...

随机推荐

  1. Entity Framework 使用sql语句分页(查询单表)

    1.查询单表 var pageSize = 2;//条数 var pageIndex = 2;//索引 var sql = @" SELECT D.* FROM ( SELECT ROW_N ...

  2. jquery动态添加/删除 tr/td

    <head runat="server"> <title></title> <!--easyui --> <link rel= ...

  3. Erlang官方站点

    YOUR ERLANG COMMUNITY SITE Welcome to erlangcentral.org, the Erlang community site where you can rea ...

  4. Matlab网格划分

    之前转载了一篇博客http://blog.sina.com.cn/s/blog_6163bdeb0102dvay.html,讲Matlab网格划分程序Distmesh,看了看程序,感觉程序写得有很多值 ...

  5. Headfirst设计模式的C++实现——简单工厂模式(Simple Factory)之二

    为了引出后续的工厂方法,把在简单工厂模式的基础上增加了新功能——加盟店 简而言之就是把原来的单一简单工厂(能生产cheese和greek两种pizza)细分成了纽约地区的和芝加哥地区的(每种地区都能生 ...

  6. MyBatis 拦截器 (实现分页功能)

    由于业务关系 巴拉巴拉巴拉 好吧 简单来说就是 原来的业务是 需要再实现类里写 selectCount 和selectPage两个方法才能实现分页功能 现在想要达到效果是 只通过一个方法就可以实现 也 ...

  7. const和define的使用区别

    在PHP中(PHP 4及以后),我们可以使用函数define()来定义常量,例如: <?php define('PI',3.14159);  //定义一个名为PI的常量 echo PI;     ...

  8. mysql 存储引擎 myisam innodb 区别

    虽然MySQL里的存储引擎不只是MyISAM与InnoDB这两个,但常用的就是它俩了.可能有站长并未注意过MySQL的存储引擎,其实存储引擎也是数据库设计里的一大重要点,那么博客系统应该使用哪种存储引 ...

  9. [python]filter

  10. Flume用来收集日志,zeppelin用来展示

    Flume:Flume是一个分布式,可依赖的,用于高效率的收集.聚类.移动大量数据的服务.Flume使用基于流数据的简单而且可扩展的架构.由于拥有可调的依赖机制和许多故障恢复机制,Flume是健壮而且 ...