您的位置:首页 > 编程语言 > Java开发

java学习多线程之卖票示例

2013-10-20 14:04 330 查看
这一节我们来说一个示例就是卖票示例:

需求:

我们现在有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这个关键字加到代码块之前就是同步代码块,加到函数上面就是同步函数。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: