多线程异常 和 事务(二)

来源:互联网 发布:android仿知乎源码 编辑:程序博客网 时间:2024/06/05 17:27

1.接着上一篇代码变形一下

首先我们在上一篇文章的基础上把代码变形的面向对象一些

package com.wei.service.impl;import java.util.ArrayList;import java.util.List;import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.Future;import java.util.concurrent.SynchronousQueue;import java.util.concurrent.ThreadFactory;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;import java.util.concurrent.atomic.AtomicInteger;import com.google.common.util.concurrent.ThreadFactoryBuilder;public class MultiThreadExceptionAndReturnValSHow {public static void main(String[] args) {final ThreadFactory threadFactory = new ThreadFactoryBuilder().setNameFormat("Orders-%d-Thread:").build();int minPoolSize = 5;int maxPoolSize = 10;//SynchronousQueue同步队列容量0,就是说线程池没有等待队列ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(minPoolSize, maxPoolSize, 60L, TimeUnit.SECONDS,new SynchronousQueue<Runnable>(), threadFactory);//测试一个Runnablefor (int i = 0; i < 5; i++) {ExceptionRunThread thread = new ExceptionRunThread();threadPoolExecutor.submit(thread);}//测试一个callablefor (int i = 0; i < 5; i++) {ExceptionCallableThread call = new ExceptionCallableThread();threadPoolExecutor.submit(call);}//测试多个callableList<Callable<String>> callList = new ArrayList<Callable<String>>();for (int i = 0; i < 5; i++) {ExceptionCallable call = new ExceptionCallable();callList.add(call);}invokeAllTask(threadPoolExecutor, callList);//等待任务完成后,关闭线程池threadPoolExecutor.shutdown();}private static <T> List<T> invokeAllTask(ThreadPoolExecutor threadPoolExecutor, List<Callable<T>> callList) {List<Future<T>> futureAll = null;List<T> resultList = new ArrayList<T>();try {futureAll = threadPoolExecutor.invokeAll(callList);} catch (InterruptedException e) {e.printStackTrace();}AtomicInteger in = new AtomicInteger(1);for (Future<T> f : futureAll) {try {T result = f.get();System.out.println("count:" + in.getAndIncrement() + ":"+ result);resultList.add(result);} catch (InterruptedException e) {e.printStackTrace();} catch (ExecutionException e) {e.printStackTrace();}}return resultList;}}class ExceptionRunThread implements Runnable {@Overridepublic void run() {try {System.out.println(Thread.currentThread().getName()+ "do something start......");if (Thread.currentThread().getName().contains("2")) {throw new RuntimeException("测试 uncheck exception");}Thread.sleep(100);// do somethingSystem.out.println(Thread.currentThread().getName()+ "do something end......");} catch (InterruptedException e) {e.printStackTrace();}}}class ExceptionCallableThread implements Callable<String> {@Overridepublic String call() {try {System.out.println(Thread.currentThread().getName()+ "do something start......");if (Thread.currentThread().getName().contains("2")) {throw new RuntimeException("测试 uncheck exception");}Thread.sleep(100);// do somethingSystem.out.println(Thread.currentThread().getName()+ "do something end......");} catch (InterruptedException e) {e.printStackTrace();}return Thread.currentThread().getName();}}


这里面有有一个重要的地方,就是线程的命名,我们借助google线程工厂的一个类,线程的命名很重要,大家可以把线程数量修改到20,
Run结果

Orders-0-Thread:do something start......Orders-1-Thread:do something start......Orders-2-Thread:do something start......Orders-3-Thread:do something start......Orders-4-Thread:do something start......Orders-5-Thread:do something start......Orders-6-Thread:do something start......Orders-7-Thread:do something start......Orders-8-Thread:do something start......Orders-9-Thread:do something start......Orders-10-Thread:do something start......Orders-11-Thread:do something start......Orders-12-Thread:do something start......Orders-13-Thread:do something start......Orders-14-Thread:do something start......Orders-0-Thread:do something end......Orders-1-Thread:do something end......Orders-4-Thread:do something end......Orders-3-Thread:do something end......Orders-6-Thread:do something end......Orders-5-Thread:do something end......Orders-8-Thread:do something end......Orders-7-Thread:do something end......Orders-9-Thread:do something end......Orders-14-Thread:do something end......Orders-11-Thread:do something end......Orders-10-Thread:do something end......Orders-13-Thread:do something end......count:1:Orders-10-Thread:count:2:Orders-11-Thread:java.util.concurrent.ExecutionException: java.lang.RuntimeException: 测试 uncheck exceptionat java.util.concurrent.FutureTask$Sync.innerGet(Unknown Source)at java.util.concurrent.FutureTask.get(Unknown Source)at com.wei.service.impl.MultiThreadExceptionAndReturnValSHow.invokeAllTask(MultiThreadExceptionAndReturnValSHow.java:63)at com.wei.service.impl.MultiThreadExceptionAndReturnValSHow.main(MultiThreadExceptionAndReturnValSHow.java:46)Caused by: java.lang.RuntimeException: 测试 uncheck exceptionat com.wei.service.impl.ExceptionCallable.call(MultiThreadExceptionAndReturnVal.java:138)at com.wei.service.impl.ExceptionCallable.call(MultiThreadExceptionAndReturnVal.java:1)at java.util.concurrent.FutureTask$Sync.innerRun(Unknown Source)at java.util.concurrent.FutureTask.run(Unknown Source)at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source)at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)at java.lang.Thread.run(Unknown Source)count:3:Orders-13-Thread:count:4:Orders-14-Thread:

输出不难理解,线程2和12线程都没有正常结束,而线程12正好运行的是有返回值的所以count:5:orders-12-Thread是异常的。

2下面我们集成到spring中去看,有了上面的代码变形,那么集成到spring中会比较容易

先看线程池业务接口类
package com.wei.service;import java.util.List;import java.util.concurrent.Callable;import com.wei.service.facade.vo.CommonResonse;public interface MultiThreadTaskExecutorService {public <T> CommonResonse<T> invokeAll(List<Callable<T>> taskList);}
实现类,我们可以看到线程执行器被包在了这个里面
package com.wei.service.impl;import java.util.ArrayList;import java.util.List;import java.util.concurrent.Callable;import java.util.concurrent.ExecutionException;import java.util.concurrent.Future;import java.util.concurrent.SynchronousQueue;import java.util.concurrent.ThreadFactory;import java.util.concurrent.ThreadPoolExecutor;import java.util.concurrent.TimeUnit;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.DisposableBean;import org.springframework.beans.factory.InitializingBean;import com.alibaba.fastjson.JSON;import com.google.common.util.concurrent.ThreadFactoryBuilder;import com.wei.service.MultiThreadTaskExecutorService;import com.wei.service.facade.vo.CommonResonse;public class MultiThreadTaskExecutorServiceImpl implementsMultiThreadTaskExecutorService, InitializingBean, DisposableBean {private Logger logger = LoggerFactory.getLogger(this.getClass());private ThreadPoolExecutor threadPoolExecutor;private int minPoolSize;private int maxPoolSize;@Overridepublic <T> CommonResonse<T> invokeAll(List<Callable<T>> taskList) {try {List<Future<T>> futures = threadPoolExecutor.invokeAll(taskList);List<T> resultList = new ArrayList<T>();for (Future<T> future : futures) {try {resultList.add(future.get());} catch (ExecutionException e) {e.printStackTrace();}}logger.info("result={}",JSON.toJSONString(resultList));} catch (InterruptedException e) {e.printStackTrace();}return null;}@Overridepublic void destroy() throws Exception {threadPoolExecutor.shutdown();}@Overridepublic void afterPropertiesSet() throws Exception {final ThreadFactory threadFactory = new ThreadFactoryBuilder()        .setNameFormat("Orders-%d")        .build();threadPoolExecutor = new ThreadPoolExecutor(minPoolSize, maxPoolSize,60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>(),threadFactory);}public int getMinPoolSize() {return minPoolSize;}public void setMinPoolSize(int minPoolSize) {this.minPoolSize = minPoolSize;}public int getMaxPoolSize() {return maxPoolSize;}public void setMaxPoolSize(int maxPoolSize) {this.maxPoolSize = maxPoolSize;}}


xm里bean的配置
<bean id="multiThreadTaskExecutorService"class="com.wei.service.impl.MultiThreadTaskExecutorServiceImpl"><property name="minPoolSize" value="5" /><property name="maxPoolSize" value="10" /></bean>

aop事务的配置
<tx:advice id="txAdvice" transaction-manager="transactionManager"><tx:attributes><tx:method name="*" propagation="REQUIRED" rollback-for="java.lang.Exception"/></tx:attributes></tx:advice><aop:config><aop:pointcut id="servicePiontCut"expression="execution(* com.wei.service..*(..))" /><aop:advisor advice-ref="txAdvice" pointcut-ref="servicePiontCut" /></aop:config>


在看业务接口类
package com.wei.service;import java.util.List;import java.util.concurrent.Callable;import com.wei.dao.entity.User;public interface CallTaskService extends Callable<List<User>>{List<User> call();}

package com.wei.service;import java.util.List;import java.util.concurrent.Callable;import com.wei.dao.entity.User;public interface CallTask2Service extends Callable<List<User>>{List<User> call();}


业务接口实现
package com.wei.service.impl;import java.util.List;import java.util.concurrent.Callable;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.wei.dao.entity.User;import com.wei.dao.mapper.UserMapper;import com.wei.service.CallTaskService;@Servicepublic class CallTaskServiceImpl implements CallTaskService ,Callable<List<User>>{@AutowiredUserMapper userMapper;@Overridepublic List<User> call() {return userMapper.select(null);}}

下面是依赖这几个接口的测试类,接口没有写大家自己补一下
package com.wei.service.impl;import java.text.SimpleDateFormat;import java.util.ArrayList;import java.util.Date;import java.util.List;import java.util.concurrent.Callable;import org.apache.ibatis.session.RowBounds;import org.springframework.beans.BeanUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Service;import com.alibaba.fastjson.JSON;import com.github.pagehelper.Page;import com.github.pagehelper.PageHelper;import com.github.pagehelper.PageInfo;import com.wei.dao.entity.User;import com.wei.dao.mapper.UserMapper;import com.wei.service.CallTask2Service;import com.wei.service.CallTaskService;import com.wei.service.MultiThreadTaskExecutorService;import com.wei.service.UserService;import com.wei.service.vo.UserVo;@Servicepublic class UserServiceImpl implements UserService{@AutowiredUserMapper userMapper;@AutowiredCallTask2Service callTask2Service;@AutowiredCallTaskService callTaskService;@AutowiredMultiThreadTaskExecutorService multiThreadTaskExecutorService;@Overridepublic void testThreadRollBack(UserVo userVo) {List<Callable<List<User>>> taskList=new ArrayList<Callable<List<User>>>();//taskList.add(new Callable<List<User>>() {//@Override//public List<User> call() throws Exception {//System.out.println("---------->"+"select");//return userMapper.select(null);//}//});//taskList.add(new Callable<List<User>>() {//@Override//public List<User> call() throws Exception {//User user=new User();//user.setCreateDate(new Date());//SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//user.setId("rollbank20160421-"+sdf.format(new Date()));//user.setName("rollback"+sdf.format(new Date()));//user.setPassword("2222222");//userMapper.insert(user);//System.out.println("---------->"+"insert and select");//userMapper.select(null);//int i=1/0;//return userMapper.select(null);//}//});taskList.add(callTask2Service);taskList.add(callTaskService);multiThreadTaskExecutorService.invokeAll(taskList);//User user=new User();//user.setCreateDate(new Date());//SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");//user.setId("rollbank20160421-"+sdf.format(new Date()));//user.setName("rollback"+sdf.format(new Date()));//user.setPassword("11111111");//userMapper.insert(user);int i=1/0;}}

通过测试,结果我就不贴出来了,我们可以看到只要是spring托管的bean切面的事务就是起作用的,new的就没有事务,runnable和callable也一样,new出来的匿名内部类spring不管理他的事务,因为他没有交给spring托管。想开启事务要自己编码。
另外线程之间也是没有影响的,一个线程异常结束,不会影响其他线程,仔细想想道理都知道,还是做实验区印证了下。再重复下,只有spring托管的bean才会去管理事务,自己new出来的不管理事务,相信自己学的,重要的说三遍,标红吧。


0 0
原创粉丝点击