spring中使用多线程
2016-07-21 00:06
459 查看
我们知道创建多线程有两种方式。
1⃣️实现runnable接口
2⃣️继承thread类
但执行多线程前必须要实例化对象,然后调用start方法才能执行。
我们知道spring通过ioc创建实例,对象被动注入到你需要使用的类中,而且,spring创建对象默认是单例的。那么该如何操作呢?
方法很简单:
1⃣️首先我们需要创建自己的线程类,也就是你要并发执行的任务:
就像下面这样:
2⃣️然后在我们的主线程类中创建线程池调用线程或直接调用线程。
就像下面这样:
注意这里我们调用线程是自己实现了一个接口去创建对象的,因为,for循环中通过反射每次都创建新的对象,每个对象创建自己的线程执行。
3⃣️下面是获取线程对象的方法:
尤其要注意!线程类一定要是多例的!
另外,如果在线程中执行其他对象中的方法,而且这个对象是单例的,不要忘了加锁标记!否则可能引起并发错误。如果只在线程类中执行或者调用的别的类是多例的,则不需要考虑这个问题。
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; } }
尤其要注意!线程类一定要是多例的!
另外,如果在线程中执行其他对象中的方法,而且这个对象是单例的,不要忘了加锁标记!否则可能引起并发错误。如果只在线程类中执行或者调用的别的类是多例的,则不需要考虑这个问题。
相关文章推荐
- Java基本语法-----java进制的转换
- Java基本语法-----java进制的转换
- JAVA学习日志(7-3-抽象类)
- Java中创建对象的5种不同方法
- 最实用的Spring Data JPA功能
- 分享Java开发的利器-Lombok
- java--02
- 【Java】myeclipse
- eclipse svn 忽略 相关文件和目录
- Spring AOP 知识整理
- Servlet处理文件上传
- java集合
- Java cxf WebService 入门[sayHello]
- Java学习历程
- Eclipse使用技巧之插件安装
- SpringMVC与Thymeleaf学习小记
- springboot学习
- SpringMVC 学习- Spring MVC 框架及基本配置
- spring data jpa 先排序后分组
- js从前端访问到springMVC后台处理返回页面的过程