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);
//测试一个Runnable
for (int i = 0; i < 5; i++) {
ExceptionRunThread thread = new ExceptionRunThread();
threadPoolExecutor.submit(thread);
}
//测试一个callable
for (int i = 0; i < 5; i++) {
ExceptionCallableThread call = new ExceptionCallableThread();
threadPoolExecutor.submit(call);
}
//测试多个callable
List<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 {
@Override
public 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 something
System.out.println(Thread.currentThread().getName()
+ "do something end......");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
class ExceptionCallableThread implements Callable<String> {
@Override
public 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 something
System.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 exception
at 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 exception
at 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 implements
MultiThreadTaskExecutorService, InitializingBean, DisposableBean {
private Logger logger = LoggerFactory.getLogger(this.getClass());
private ThreadPoolExecutor threadPoolExecutor;
private int minPoolSize;
private int maxPoolSize;
@Override
public <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;
}
@Override
public void destroy() throws Exception {
threadPoolExecutor.shutdown();
}
@Override
public 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;
@Service
public class CallTaskServiceImpl implements CallTaskService ,Callable<List<User>>{
@Autowired
UserMapper userMapper;
@Override
public 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;
@Service
public class UserServiceImpl implements UserService{
@Autowired
UserMapper userMapper;
@Autowired
CallTask2Service callTask2Service;
@Autowired
CallTaskService callTaskService;
@Autowired
MultiThreadTaskExecutorService multiThreadTaskExecutorService;
@Override
public 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出来的不管理事务,相信自己学的,重要的说三遍,标红吧。