0 0

求分析!!!JAVA 多线程问题 10

Java 多线程 模拟  3个售票处  共同 卖 100张票  

 

统计 各个窗口 卖了多少张票  

 

统计结果  为什么 总有一个售票处是卖掉50张左右  其他两个售票处 各自卖掉25张左右

 

还有我本机 线程1总是卖不到最后一张  

 

求解~~~~~~~~~

 

代码如下:

 

public class Wicket implements Runnable {
	public Wicket(int tickets) {
		this.tickets = tickets;
	}

	public Wicket() {
	}

	private int tickets;
	private int soldT=1;

	@Override
	public void run() {
		String name = Thread.currentThread().getName();
		int a=0;
		synchronized (this) {
			for (;;) {
				if (soldT>100) {
					break;
				}
				System.out.println(name + "号窗口 卖掉了	" + soldT++ + "	号票");
				a++;
				try {
					this.notifyAll();
					this.wait(10);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}
		System.out.println(Thread.currentThread().getName()+"	"+a);
	}
	
	public static void main(String[] args) {
		System.out.println("	最后100张票了!  快来买啊		");
		System.out.println("-----------------------------------------");
		int tickets=100;
		Wicket wicket=new Wicket(tickets);
		
		
		Thread wicket1=new Thread(wicket,"1");
		Thread wicket2=new Thread(wicket,"2");
		Thread wicket3=new Thread(wicket,"3");
		wicket1.start();
		wicket2.start();
		wicket3.start();
	}
	

	public int getTickets() {
		return tickets;
	}

	public void setTickets(int tickets) {
		this.tickets = tickets;
	}

	public int getSeldT() {
		return soldT;
	}

	public void setSeldT(int seldT) {
		this.soldT = seldT;
	}

}
2012年9月05日 21:44

8个答案 按时间排序 按投票排序

0 0

注释掉代码 24行 //this.notifyAll();  问题解决


原因不是很清楚 我记着是 notifyAll是与wait用在一起的 不知道你用在此处的目的何在 所以导致了这种现象的出现

2012年9月06日 12:57
0 0

你锁的什么东西啊,3个对象,3把锁,和没锁有什么区别?

2012年9月06日 11:45
0 0

放到for里面模拟每次重新锁定

for (;;) {
	synchronized (this) {
		if (soldT>100) {
			break;
		}
		System.out.println(name + "号窗口 卖掉了	" + soldT++ + "	号票");
		a++;
		this.notifyAll();
	}
	try {
		Thread.sleep(10);
	} catch (InterruptedException e) {
	}
}


给其一个相对平等的启动时机
synchronized (wicket) {
	wicket1.start();
	wicket2.start();
	wicket3.start();
}


结果:
1号窗口 卖掉了 100 号票
2 33
3 33
1 34

1号窗口 卖掉了 100 号票
2 33
3 33
1 34

2号窗口 卖掉了 100 号票
1 33
3 33
2 34

当我去掉:System.out.println(name + "号窗口 卖掉了 " + soldT++ + " 号票");
时,几个线程就定在了Thread.sleep(10);这个是一个native方法,很奇怪。

2012年9月06日 09:41
0 0

代码没看仔细啊,你的

synchronized (this) {
			for (;;) {


放在for外面了,应该放到里面
for (;;) {
    synchronized (this) {

2012年9月06日 09:18
0 0

this.wait(10);去掉就好了。

2012年9月06日 09:13
0 0

执行notifyAll()时,

引用
被唤醒的线程将以常规方式与在该对象上主动同步的其他所有线程进行竞争;例如,唤醒的线程在作为锁定此对象的下一个线程方面没有可靠的特权或劣势。


出现你本机的那种现象可能是你机器cpu的线程调度的特殊性,说一下你的机器配置,或者你换个机器再试试看。

程序我执行过,没有出现你所描述的问题。

2012年9月06日 08:46
0 0

代码本身没问题

比如我机器的执行结果是:
3号窗口 卖掉了  100 号票
1   36
2   27
3   37

2号窗口 卖掉了  100 号票
3   22
1   28
2   50

1号窗口 卖掉了  100 号票
2   28
3   43
1   29

多执行几次即可,线程执行顺序不可知,所以结果可以认为是随机.


public class Wicket implements Runnable {
    public Wicket(Integer tickets) {
        this.tickets = tickets;
    }

    public Wicket() {
    }

    private Integer tickets;
    private int soldT=1;

    @Override
    public void run() {
        String name = Thread.currentThread().getName();
        int a=0;
        for (;;) {
            synchronized (tickets) {
                if (soldT > 100) {
                    break;
                }
                System.out.println(name + "号窗口 卖掉了  " + soldT++ + " 号票");
            }
            a++;
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
        System.out.println(Thread.currentThread().getName()+"   "+a);
    }
    
    
    public int getTickets() {
        return tickets;
    }

    public void setTickets(int tickets) {
        this.tickets = tickets;
    }

    public int getSeldT() {
        return soldT;
    }

    public void setSeldT(int seldT) {
        this.soldT = seldT;
    }

    public static void main(String[] args) {
        System.out.println("    最后100张票了!  快来买啊     ");
        System.out.println("-----------------------------------------");
        Integer tickets= new Integer(100);
        Wicket wicket=new Wicket(tickets);
       
        
        Thread wicket1=new Thread(wicket,"1");
        Thread wicket2=new Thread(wicket,"2");
        Thread wicket3=new Thread(wicket,"3");
        wicket1.start();
        wicket2.start();
        wicket3.start();
    }
    

}


我修改了一下
            synchronized (tickets) {
                if (soldT > 100) {
                    break;
                }
                System.out.println(name + "号窗口 卖掉了  " + soldT++ + " 号票");
            }
锁的范围越小越好,而且锁票即可.


           try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            通过睡眠来搞定 等待.

2012年9月05日 22:07
0 0

===========main.java==============

class T4E02 
{
	public static void main(String[] args) 
	{
		Resource rs = new Resource(100);

		for (int i=0;i<10 ;i++ )
		{
			new Thread(new Seller(i,rs)).start();
		}
	}
}


====Resource。java======================
/**
 *	资源类
 *	定义了票的总数,和同步了的售票方法
 */
class Resource
{
	int ticketNum = 50;
	boolean flag = false ; // 定义票是否卖完

	public Resource(){}
	public Resource(int num)
	{
		this.ticketNum = num;
	}

	public synchronized void sellTicket(Seller s)
	{
		if (ticketNum > 0)
		{
			System.out.println("第" + s.num + "售票点卖出了第" + ticketNum + "张票……");
			ticketNum--;
		}
		else 
		{
			flag = true;
		}
	}
}

===============Seller .java=============
/**
 *	售票点类
 *	
 */
class Seller implements Runnable
{
	int num;
	Resource rs;

	public Seller(int num,Resource rs)
	{
		this.num = num;
		this.rs = rs;
	}

	public final void run()
	{
		while (!rs.flag)
		{
			/**
			 *  调用资源类的同步方法
			 */ 
			rs.sellTicket(this); 

			try
			{
				Thread.sleep(100);
			}
			catch (InterruptedException e)
			{
				e.printStackTrace();
			}
		}
	}
}

2012年9月05日 22:02

相关推荐

Global site tag (gtag.js) - Google Analytics