对于JAVA多线程卖票小程序的理解

  昨天把多线程重新看了一遍,发现自己还是有许多需要理解的地方,现在写一篇总结。

  一:利用继承Thread类会出现的问题:

public class SellTicketsThread extends Thread {
	private   int tickets = 10;

	public SellTicketsThread(String name) {
		super(name);
	}

	@Override
	public void run() {

		while (true) {
			if(tickets<=0) break;
			synchronized (this) {
				try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				if (tickets > 0) {
					System.out.println(Thread.currentThread().getName() + "卖出第"
							+ tickets-- + "张票");
				}
			}
		}

	}

}

public class SellTicketsThreadDemo {

	public static void main(String[] args) {
		SellTicketsThread t1 = new SellTicketsThread("窗口1");
		SellTicketsThread t2 = new SellTicketsThread("窗口2");
		SellTicketsThread t3 = new SellTicketsThread("窗口3");
		 
		 t1.start();
		 t2.start();
		 t3.start();

	}
}

这样的话看上去是用了同步锁锁住了对象,但运行结果却是不符合逻辑的。三个窗口共卖了30张票。

窗口2卖出第10张票
窗口1卖出第10张票
窗口3卖出第10张票
窗口3卖出第9张票
窗口2卖出第9张票
窗口1卖出第9张票
窗口3卖出第8张票
窗口1卖出第8张票
窗口2卖出第8张票
窗口2卖出第7张票
窗口3卖出第7张票
窗口1卖出第7张票
窗口2卖出第6张票
窗口1卖出第6张票
窗口3卖出第6张票
窗口2卖出第5张票
窗口1卖出第5张票
窗口3卖出第5张票
窗口2卖出第4张票
窗口3卖出第4张票
窗口1卖出第4张票
窗口2卖出第3张票
窗口1卖出第3张票
窗口3卖出第3张票
窗口2卖出第2张票
窗口1卖出第2张票
窗口3卖出第2张票
窗口2卖出第1张票
窗口3卖出第1张票
窗口1卖出第1张票

  二:利用Runnale接口实现

package SellTickets;

public class SellTicketsThread implements Runnable{
	private int tickets = 10;
	@Override
	public void run() {
		while(true){
			if(tickets<=0) break;
			 synchronized(this){
			 try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			 if(tickets>0){
				 System.out.println(Thread.currentThread().getName()+"卖出第"+tickets--+"张票");
			 }
		 }
		}
		
	}

}

public class SellTicketsThreadDemo {

	public static void main(String[] args) {
		SellTicketsThread st = new SellTicketsThread();
		Thread t1 = new Thread(st,"窗口一");
		Thread t2 = new Thread(st,"窗口二");
		Thread t3 = new Thread(st,"窗口三");
		 
		 t1.start();
		 t2.start();
		 t3.start();

	}

}

  

窗口一卖出第10张票
窗口一卖出第9张票
窗口一卖出第8张票
窗口三卖出第7张票
窗口二卖出第6张票
窗口二卖出第5张票
窗口三卖出第4张票
窗口三卖出第3张票
窗口三卖出第2张票
窗口三卖出第1张票

 这样就不会有问题了,因为三个线程共享的是同一个Runnable开辟的内存.网上几乎都是用的这种方法,能不能不用Runnable接口也能实现这个效果呢??接下来是用Thread实现的两种方式,如有错误之处还请指正.

三:在继承Thread的类中定义静态变量和静态方法,将锁加在静态方法上,让多个线程共享。

public class SellTicketsThread extends Thread {
	public SellTicketsThread(String name){
		super(name);
	}
	public SellTicketsThread(){
	}
	private static int tickets =10;
	public synchronized static void take(){
		try {
			Thread.sleep(100);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		if(tickets>0){
			System.out.println(Thread.currentThread().getName() + "卖出第"
				+ tickets-- + "张票");
		}
	}
	@Override
	public void run() {
		while(true){
			take();
		} 
	}
}
public class SellTicketsThreadDemo {

	public static void main(String[] args) {
		SellTicketsThread t1 = new SellTicketsThread("窗口1");
		SellTicketsThread t2 = new SellTicketsThread("窗口2");
		SellTicketsThread t3 = new SellTicketsThread("窗口3");
		 
		 t1.start();
		 t2.start();
		 t3.start();

	}
}

  

窗口1卖出第10张票
窗口1卖出第9张票
窗口3卖出第8张票
窗口3卖出第7张票
窗口3卖出第6张票
窗口2卖出第5张票
窗口2卖出第4张票
窗口3卖出第3张票
窗口1卖出第2张票
窗口1卖出第1张票

 四:定义一个锁对象,让多个线程共同用同一个锁,同时将共享变量定义成静态的。

public class SellTicketsThread extends Thread {
	Object o =null;
	private static int tickets = 10;
	public SellTicketsThread(String name,Object o){
		super(name);
		this.o = o;
	}
	public SellTicketsThread(){
	}
	 
	@Override
	public void run() {
		while(true){
			while(true){
				if(tickets<=0) break;
				 synchronized(o){
				 try {
					Thread.sleep(100);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
				 if(tickets>0){
					 System.out.println(Thread.currentThread().getName()+"卖出第"+tickets--+"张票");
				 }
			 }
		} 
	}
}
}
public class SellTicketsThreadDemo {

	public static void main(String[] args) {
		Object o = new Object();//共同的锁
		SellTicketsThread t1 = new SellTicketsThread("窗口1",o);
		SellTicketsThread t2 = new SellTicketsThread("窗口2",o);
		SellTicketsThread t3 = new SellTicketsThread("窗口3",o);
		 
		 t1.start();
		 t2.start();
		 t3.start();

	}
}

  

窗口1卖出第10张票
窗口1卖出第9张票
窗口1卖出第8张票
窗口3卖出第7张票
窗口3卖出第6张票
窗口3卖出第5张票
窗口3卖出第4张票
窗口2卖出第3张票
窗口2卖出第2张票
窗口2卖出第1张票

   还需要注意的是,同步代码块的锁对象是任意对象。所以可以用Object做为一个锁。而同步方法(非静态)的锁对象是 this。静态方法的锁对象是类的字节码文件对象。

 

posted @ 2015-11-18 22:06  樱花庄的龙之介大人  阅读(...)  评论(...编辑  收藏