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

spring中使用多线程

2016-07-21 00:06 459 查看
我们知道创建多线程有两种方式。

1⃣️实现runnable接口

2⃣️继承thread类

但执行多线程前必须要实例化对象,然后调用start方法才能执行。

我们知道spring通过ioc创建实例,对象被动注入到你需要使用的类中,而且,spring创建对象默认是单例的。那么该如何操作呢?

方法很简单:

1⃣️首先我们需要创建自己的线程类,也就是你要并发执行的任务:

就像下面这样:

@Component("oneTask")
@Scope("prototype")
public class OneTask extends Thread {
private HashMap item;

public OneTask(HashMap item) {
this.item = item;
}

public void setItem(HashMap item){
this.item = item;
}
public OneTask(){

}
public void run(){
try {
System.out.println(">>>>"+Thread.currentThread().getName()+",正在执行第"+(time++) +"次");
HotelBaseInfo hbi = new HotelBaseInfo();
if(item!=null){
System.out.println(item.toString());
System.out.println((String)item.get("UpdatedTime"));
FileUtil.write(item.toString(),"/Users/D_xiao/工作/java_file_write/thisHotel.txt");
hbi.newLoadFromMap(item);
/********/
HotelBaseInfo oldHbi = (HotelBaseInfo)hotelBaseDao.queryOne("from HotelBaseInfo h where h.hotelId = ?", new Object[]{hbi.getHotelId()});
if (oldHbi!=null) {
//System.out.println(">>>>>>获取酒店 id: "+oldHbi.getHotelId());
// 说明数据库里面有这条数据,现在就是要使用更新时间做一下对比。
if (!oldHbi.getUpdatedTime().equals(hbi.getUpdatedTime())) {
System.out.println(">>>>>>>>>>>>数据有更新");
// 更新时间不一样,说明数据有更新,先删除原来的数据,再换成新的,用事务控制
hotelBaseDao.delete(oldHbi);
hbi.setId(UUIDTool.getUUID());
hotelBaseDao.add(hbi);
// 更新此酒店具体信息
//  updateDetailInfo(hbi.getHotelId());
}
}else{
System.out.println(">>>>>>>>>没有该酒店,添加新记录,并添加子节点");
hbi.setId(UUIDTool.getUUID());
hotelBaseDao.add(hbi);
updateDetailInfo(hbi.getHotelId());
}
}
} catch (IllegalArgumentException | IllegalAccessException e) {
e.printStackTrace();
System.out.println("==================================================================");
System.out.println("更新HotelBaseInfo失败!"+e.getMessage());
System.out.println("==================================================================");
}
//}
}
注意:这里我们写了一个set方法,可以通过set方法,往线程中传递参数!而且这个子线程要有@Scope("prototype")注解,表示该类是多例的!不然实例化对象只会创建一次!


2⃣️然后在我们的主线程类中创建线程池调用线程或直接调用线程。

就像下面这样:

long start=System.currentTimeMillis();
System.out.println(">>>>>>>>>>开始下载");
HashMap m = xmlToDomain
.analyseXml(networkUtil.sendGet("http://api.test.lohoo.com/xml/v2.0/hotel/hotellist.xml"));
HashMap hotelListMap = (HashMap) m.get("Hotels");
FileUtil.write(hotelListMap.toString(),"/Users/D_xiao/工作/java_file_write/hotelList.txt");
System.out.println(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>已下载酒店跟数据");
ArrayList<HashMap> hotelList = (ArrayList<HashMap>) hotelListMap.get("Hotel");
System.out.println(">>>>>>>>>>>>>以获取 Hotel根节点");
ExecutorService pool = Executors.newFixedThreadPool(10);
int i = 0;
for (HashMap item : hotelList) {
OneTask one = hotelTaskService.getTask();
one.setItem(item);
pool.execute(one);
}
updateGEOInfo();
pool.shutdown();
long end=System.currentTimeMillis();


注意这里我们调用线程是自己实现了一个接口去创建对象的,因为,for循环中通过反射每次都创建新的对象,每个对象创建自己的线程执行。

3⃣️下面是获取线程对象的方法:

@Component("hotelTaskService")
public class HotelTaskServiceImpl {

public OneTask getTask(){
ApplicationContext applicationContext = GETApplicationContext.getApplicationContext();
OneTask oneTask = (OneTask) applicationContext.getBean("oneTask");
return oneTask;
}
}


尤其要注意!线程类一定要是多例的!

另外,如果在线程中执行其他对象中的方法,而且这个对象是单例的,不要忘了加锁标记!否则可能引起并发错误。如果只在线程类中执行或者调用的别的类是多例的,则不需要考虑这个问题。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: