实现Runnable接口,可以实现资源共享,网上很多卖票例子是生成多个个线程,但只声明了一个Runnable对象(共享变量票数在Runnable对象里),然后传给多个Thread线程,达到资源共享。
可参考:http://blog.csdn.net/lyt_7cs1dn9/article/details/52486317
本例子是直接在main生成了一个map作为共享变量,然后传给多个Runnable的构造器中,再把多个Runnable对象传入Thread构造器生成多个线程。
直接上例子:
package com.lyt.study.controller;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
/**
* Created by lyt on 2016/9/8 0008.
*/
class SaleTicketThread implements Runnable{
private String saleWindowName; //售票窗口名称
private Map<String,Boolean> ticketMap; //车票池
//构造方法
this.saleWindowName = saleWindowName;
this.ticketMap = ticketMap;
}
public void run() {
System.out.println(saleWindowName ); //输出线程名称
Set<String> keySet= ticketMap.keySet();
synchronized(ticketMap){ //synchronized同步锁住车票map
for(String s:keySet){
if(!ticketMap.get(s)){
System.out.println(saleWindowName +":" + s + "已被售出。");
ticketMap.put(s,true);
}
}
}
}
}
public class TicketSaleMain {
public static void main(String[] args){
//首先需要定义一个火车票池 key代表第几张票,value代表是否卖出
Map<String,Boolean> ticketMap = new HashMap<String,Boolean>();
for(int i=1;i<=50;i++){
ticketMap.put("第"+i+"张票",false); //起始都没卖出,value为false
}
SaleTicketThread stt1= new SaleTicketThread("窗口1",ticketMap); //把票池map给4个窗口共享
SaleTicketThread stt2= new SaleTicketThread("窗口2",ticketMap); //把票池map给4个窗口共享
SaleTicketThread stt3= new SaleTicketThread("窗口3",ticketMap); //把票池map给4个窗口共享
SaleTicketThread stt4= new SaleTicketThread("窗口4",ticketMap); //把票池map给4个窗口共享
Thread t1=new Thread(stt1);
Thread t2=new Thread(stt2);
Thread t3=new Thread(stt3);
Thread t4=new Thread(stt4);
t1.start(); //启动线程
t2.start(); //启动线程
t3.start(); //启动线程
t4.start(); //启动线程
}
}
运行结果:
窗口1
窗口2
窗口1:第45张票已被售出。
窗口1:第32张票已被售出。
窗口1:第33张票已被售出。
窗口3
窗口1:第17张票已被售出。
窗口1:第26张票已被售出。
窗口1:第34张票已被售出。
窗口1:第24张票已被售出。
窗口4
窗口1:第44张票已被售出。
窗口1:第27张票已被售出。
窗口1:第31张票已被售出。
窗口1:第36张票已被售出。
窗口1:第15张票已被售出。
窗口1:第1张票已被售出。
窗口1:第2张票已被售出。
窗口1:第16张票已被售出。
窗口1:第30张票已被售出。
窗口1:第25张票已被售出。
窗口1:第50张票已被售出。
窗口1:第35张票已被售出。
窗口1:第14张票已被售出。
窗口1:第42张票已被售出。
窗口1:第43张票已被售出。
窗口1:第12张票已被售出。
窗口1:第11张票已被售出。
窗口1:第28张票已被售出。
窗口1:第48张票已被售出。
窗口1:第13张票已被售出。
窗口1:第46张票已被售出。
窗口1:第47张票已被售出。
窗口1:第49张票已被售出。
窗口1:第7张票已被售出。
窗口1:第29张票已被售出。
窗口1:第41张票已被售出。
窗口1:第20张票已被售出。
窗口1:第40张票已被售出。
窗口1:第4张票已被售出。
窗口1:第21张票已被售出。
窗口1:第37张票已被售出。
窗口1:第10张票已被售出。
窗口1:第3张票已被售出。
窗口1:第38张票已被售出。
窗口1:第9张票已被售出。
窗口1:第8张票已被售出。
窗口1:第18张票已被售出。
窗口1:第22张票已被售出。
窗口1:第19张票已被售出。
窗口1:第6张票已被售出。
窗口1:第23张票已被售出。
窗口1:第39张票已被售出。
窗口1:第5张票已被售出。
由上述结果可以知道,四个线程都执行了,只是最先先执行的线程把map对象锁起来,所有的票都卖光了,其他线程都没有票卖了。
把run方法的synchronized换下位置,如下:
public void run() {
System.out.println(saleWindowName );
Set<String> keySet= ticketMap.keySet();
for(String s:keySet){
synchronized(ticketMap){
if(!ticketMap.get(s)){
System.out.println(saleWindowName +":" + s + "已被售出。");
ticketMap.put(s,true);
}
}
}
}
执行结果:
窗口2
窗口1
窗口2:第45张票已被售出。
窗口2:第32张票已被售出。
窗口2:第33张票已被售出。
窗口2:第17张票已被售出。
窗口2:第26张票已被售出。
窗口2:第34张票已被售出。
窗口4
窗口3
窗口1:第24张票已被售出。
窗口1:第44张票已被售出。
窗口1:第27张票已被售出。
窗口1:第31张票已被售出。
窗口1:第36张票已被售出。
窗口1:第15张票已被售出。
窗口1:第1张票已被售出。
窗口1:第2张票已被售出。
窗口1:第16张票已被售出。
窗口1:第30张票已被售出。
窗口1:第25张票已被售出。
窗口1:第50张票已被售出。
窗口1:第35张票已被售出。
窗口1:第14张票已被售出。
窗口1:第42张票已被售出。
窗口1:第43张票已被售出。
窗口1:第12张票已被售出。
窗口1:第11张票已被售出。
窗口1:第28张票已被售出。
窗口1:第48张票已被售出。
窗口1:第13张票已被售出。
窗口1:第46张票已被售出。
窗口1:第47张票已被售出。
窗口1:第49张票已被售出。
窗口1:第7张票已被售出。
窗口1:第29张票已被售出。
窗口1:第41张票已被售出。
窗口1:第20张票已被售出。
窗口1:第40张票已被售出。
窗口1:第4张票已被售出。
窗口1:第21张票已被售出。
窗口1:第37张票已被售出。
窗口1:第10张票已被售出。
窗口1:第3张票已被售出。
窗口1:第38张票已被售出。
窗口1:第9张票已被售出。
窗口1:第8张票已被售出。
窗口1:第18张票已被售出。
窗口1:第22张票已被售出。
窗口1:第19张票已被售出。
窗口1:第6张票已被售出。
窗口1:第23张票已被售出。
窗口1:第39张票已被售出。
窗口1:第5张票已被售出。
从这次结果可以看出,窗口1和窗口2都有卖票,实现了多线程。