线程同步问题

J2EE 码拜 10年前 (2015-04-10) 970次浏览 0个评论
 

需求:编写三各类Ticket、SealWindow、TicketSealCenter分别代表票信息、售票窗口、售票中心。售票中心分配一定数量的票,由若干个售票窗口进行出售。

运行的时候有重复的票号,我已经在卖票的方法上添加了synchronized关键字,还是会出现问题,但是我找不到问题出在哪里了,谢谢大家了

public class TicketDemo {

	public static void main(String[] args) {
		new Thread(new SealWindow("1号窗口")).start();
		new Thread(new SealWindow("2号窗口")).start();
		new Thread(new SealWindow("3号窗口")).start();
		new Thread(new SealWindow("4号窗口")).start();
	}
}
//票信息
class Ticket {
	private static int ticketid;

	public static int getTicketid() {
		return ticketid;
	}

	public static void setTicketid(int ticket) {
		ticketid = ticket;
	}
}
//售票窗口
class SealWindow implements Runnable {
	private String ticketname;
	TicketSealCenter tsc = null;;

	public SealWindow(String ticketname){
		this.ticketname = ticketname;
		tsc = TicketSealCenter.getInstance();
	}
	public void sellTicket(){

		while(!tsc.hasTicket()){
			System.out.println(ticketname+"卖出了第" + tsc.getid()+"号票!");
			if (tsc.hasTicket()) {
				System.out.println(ticketname+"的票已卖完!");
			}
		}

	}
	public void run() {
		sellTicket();
	}
}
//售票中心
class TicketSealCenter {
	private static TicketSealCenter tsc = new TicketSealCenter();
	private static Ticket ticket = new Ticket();

	private static int sumticket = 100;
	private static boolean flag = false;

	private TicketSealCenter(){}

	public static TicketSealCenter getInstance(){
		return tsc;
	}
	//询问是否有票,设置票面ID,并返回该ID
	public static synchronized boolean hasTicket(){
		if(sumticket > 0){
			ticket.setTicketid(sumticket);
			sumticket--;
		}else {
			flag =true;
		}
		return flag;
	}
	public int getid(){
		return ticket.getTicketid();
	}
}
线程同步问题
因为你的synchronized是加在对象上的,但是你在建线程的时候,又新建了好几个匿名对象,这就意味着每个对象都有它自己的synchronized,所以这几个线程也就不互斥,因为它们不共享synchronized。正确的做法是只需要建一个对象,然后让这几个线程共享一个对象。像“1号窗口”、“2号窗口”可以设置为线程的名字,而不是对象的属性。
线程同步问题
15分
public class TicketDemo {
 
    public static void main(String[] args) { 
    	SealWindow myWindow=new SealWindow();
        new Thread(myWindow,"1号窗口").start();
        new Thread(myWindow,"2号窗口").start();
        new Thread(myWindow,"3号窗口").start();
        new Thread(myWindow,"4号窗口").start();
    }
}
//票信息
class Ticket {
    private static int ticketid;
 
    public static int getTicketid() {
        return ticketid;
    }
     
    public static void setTicketid(int ticket) {
        ticketid = ticket;
    }
}
//售票窗口
class SealWindow implements Runnable {
    TicketSealCenter tsc = null;
    public SealWindow(){
        tsc = TicketSealCenter.getInstance();
    }
    public void sellTicket(){
        while(!tsc.hasTicket()){
           // System.out.println(Thread.currentThread().getName()+"卖出了第" + tsc.getid()+"号票!");
            if (tsc.hasTicket()) {
                System.out.println(Thread.currentThread().getName()+"的票已卖完!");
            }
        }
         
    }
    public void run() {
        sellTicket();
    }
}
//售票中心
class TicketSealCenter {
    private static TicketSealCenter tsc = new TicketSealCenter();
    private static Ticket ticket = new Ticket();
     
    private static int sumticket = 100;
    private static boolean flag = false;
     
    private TicketSealCenter(){}
     
    public static TicketSealCenter getInstance(){
        return tsc;
    }
    //询问是否有票,设置票面ID,并返回该ID
    public static synchronized boolean hasTicket(){
        if(sumticket > 0){
            ticket.setTicketid(sumticket);
            System.out.println(Thread.currentThread().getName()+"卖出了第" + tsc.getid()+"号票!");
            sumticket--;
        }else {
            flag =true;
        }
        return flag;
    }
    public int getid(){
        return ticket.getTicketid();
    }
}
线程同步问题
5分
引用 1 楼 sima1989 的回复:

因为你的synchronized是加在对象上的,但是你在建线程的时候,又新建了好几个匿名对象,这就意味着每个对象都有它自己的synchronized,所以这几个线程也就不互斥,因为它们不共享synchronized。正确的做法是只需要建一个对象,然后让这几个线程共享一个对象。像“1号窗口”、“2号窗口”可以设置为线程的名字,而不是对象的属性。

您说的不对吧,不是因为创建了多个对象,而是因为
 while(!tsc.hasTicket()){
            System.out.println(ticketname+”卖出了第” + tsc.getid()+”号票!”);
这句并不能保证调用完成tsc.hasTicket方法之后马上执行输出语句,所以要不给这句上面加锁,但是只能加静态锁。或者就是把这句输出语句加到tsc.hasTicket他的实现里面。

线程同步问题
5分
恩  主要楼主用的是单例设计模式,不管创建多少个SealWindow,共享的都是一个TicketSealCenter对象。你的意思我在上述代码中已经有所体现了。
线程同步问题
5分
很简单的代码,撸主给弄好凌乱,很简单的锁机制,撸主却乱加。
减票方法你是加锁了,可是获取票的方法你考虑过么?
如果一个线程都执行了public static synchronized boolean hasTicket()这个方法后,执行权交给另一个线程,另一个线程也跑了这个方法,后面类推,接着多个线程开始执行public int getid()方法,你觉得票是多了呢,还是少了呢?
线程同步问题
引用 4 楼 sima1989 的回复:

恩  主要楼主用的是单例设计模式,不管创建多少个SealWindow,共享的都是一个TicketSealCenter对象。你的意思我在上述代码中已经有所体现了。

多谢了 我刚开始学java 思路有些混乱 之后自己又缕清了思路 重新写了下 现在不会出现安全问题了 还是十分的感谢你


CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明线程同步问题
喜欢 (0)
[1034331897@qq.com]
分享 (0)

文章评论已关闭!