局方要求项目满足大批量工单提交,所以这几天学习了下线程池,这里分享一下,其中还有个遇到的问题。如果代码写的有问题,欢迎大神指点。
首先这里运用最简单的线程池创建方法Executors.newFixedThreadPool(5),这里是创建5个线程,不太明白的同学可以去搜索一下,其实底层还是运用 new ThreadPoolExecutor()。这里的队列没有指定长度默认为2147483647(integer最大值,够用了)
这是java的源码:
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
言归正传,线程的创建使用了两个方法,一个是有回参的还有个是无回参。
先说有回参的,这个是实现Callable接口的,这个接口是有返回值的,我们可以利用有参构造传参。
public class CallableTest implements Callable<DaoTest>{
private String id;
public CallableTest(String id) {
this.id=id;
}
@Override
public DaoTest call() throws Exception {
System.out.println("线程 "+Thread.currentThread().getName()+"开始执行"+new Date());
DaoTest test=new DaoTest();//这个是模拟业务,从数据库查询数据。
DaoTest daotest = test.byid(id);
System.out.println("线程 "+Thread.currentThread().getName()+"结束执行"+new Date());
return daotest;
}
}
这个是测试类
public class ControllTest {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService exec = Executors.newFixedThreadPool(3);
List<Future<DaoTest>> list = new ArrayList<Future<DaoTest>>();
for (int i = 0; i < 5; i++) {
CallableTest callable = new CallableTest(i+"");//创建Callable接口实例
Future<DaoTest> csf = exec.submit(callable);
list.add(csf);
}
for (Future<DaoTest>fs:list) {
try {
System.out.println(fs.get().toString());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
exec.shutdown();
运行的结果
线程 pool-1-thread-3开始执行Wed Oct 17 17:43:32 CST 2018
线程 pool-1-thread-2开始执行Wed Oct 17 17:43:32 CST 2018
线程 pool-1-thread-1开始执行Wed Oct 17 17:43:32 CST 2018
线程 pool-1-thread-3结束执行Wed Oct 17 17:43:36 CST 2018
线程 pool-1-thread-3开始执行Wed Oct 17 17:43:36 CST 2018
线程 pool-1-thread-2结束执行Wed Oct 17 17:43:36 CST 2018
线程 pool-1-thread-2开始执行Wed Oct 17 17:43:36 CST 2018
线程 pool-1-thread-1结束执行Wed Oct 17 17:43:36 CST 2018
DaoTest [name=null, age=null, phone=null, addr=null, id=null]
DaoTest [name=ning, age=1, phone=null, addr=phone, id=1]
DaoTest [name=dan, age=18, phone=null, addr=xiaoshuo, id=2]
线程 pool-1-thread-3结束执行Wed Oct 17 17:43:40 CST 2018
线程 pool-1-thread-2结束执行Wed Oct 17 17:43:40 CST 2018
DaoTest [name=ning是, age=3, phone=null, addr=phone, id=3]
DaoTest [name=nihao, age=33, phone=null, addr=phone, id=4]
其实我刚开始是直接在for循环打印日志,之前是这样写的
public class ControllTest {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService exec = Executors.newFixedThreadPool(3);
List<Future<DaoTest>> list = new ArrayList<Future<DaoTest>>();
for (int i = 0; i < 5; i++) {
CallableTest callable = new CallableTest(i+"");//创建Callable接口实例
Future<DaoTest> csf = exec.submit(callable);
list.add(csf);
System.out.println(csf.get().toString());
// get()方法用来获取执行结果,这个方法会产生阻塞,会一直等到任务执行完毕才返回执行结果;
}
for (Future<DaoTest>fs:list) {
try {
System.out.println(fs.get().toString());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
exec.shutdown();
下面是执行的结果,可以看到虽然使用了线程池,但是变成单线程执行,其他线程阻塞了,因为csf.get()这个方法会产生线程阻塞,我这里直接获取结果,从而产生其他线程阻塞,这个在项目运用中需要注意。
线程 pool-1-thread-1开始执行Wed Oct 17 17:45:44 CST 2018
线程 pool-1-thread-1结束执行Wed Oct 17 17:45:48 CST 2018
DaoTest [name=null, age=null, phone=null, addr=null, id=null]
线程 pool-1-thread-2开始执行Wed Oct 17 17:45:48 CST 2018
线程 pool-1-thread-2结束执行Wed Oct 17 17:45:52 CST 2018
DaoTest [name=ning, age=1, phone=null, addr=phone, id=1]
线程 pool-1-thread-3开始执行Wed Oct 17 17:45:52 CST 2018
线程 pool-1-thread-3结束执行Wed Oct 17 17:45:56 CST 2018
DaoTest [name=dan, age=18, phone=null, addr=xiaoshuo, id=2]
线程 pool-1-thread-1开始执行Wed Oct 17 17:45:56 CST 2018
线程 pool-1-thread-1结束执行Wed Oct 17 17:46:00 CST 2018
DaoTest [name=ning是, age=3, phone=null, addr=phone, id=3]
线程 pool-1-thread-1开始执行Wed Oct 17 17:46:00 CST 2018
线程 pool-1-thread-1结束执行Wed Oct 17 17:46:04 CST 2018
DaoTest [name=nihao, age=33, phone=null, addr=phone, id=4]
DaoTest [name=null, age=null, phone=null, addr=null, id=null]
DaoTest [name=ning, age=1, phone=null, addr=phone, id=1]
DaoTest [name=dan, age=18, phone=null, addr=xiaoshuo, id=2]
DaoTest [name=ning是, age=3, phone=null, addr=phone, id=3]
DaoTest [name=nihao, age=33, phone=null, addr=phone, id=4]
接下来我们看下Runnable接口,首先实现Runnable
public class RunnableService implements Runnable{
String id;
public RunnableService(String id) {
this.id=id;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@Override
public void run() {
try {
System.out.println("线程 "+Thread.currentThread().getName()+"开始执行"+new Date());
DaoTest test=new DaoTest();
DaoTest daotest = test.byid(id);
System.out.println(daotest.toString());
System.out.println("线程 "+Thread.currentThread().getName()+"结束执行"+new Date());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
接着测试类
public class ControllTest {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService poll = Executors.newFixedThreadPool(3);
for (int i = 0; i <5; i++) {
RunnableService run=new RunnableService(i+"");
poll.execute(run);
}
poll.shutdown();
}
}
执行结果
线程 pool-1-thread-2开始执行Wed Oct 17 18:02:46 CST 2018
线程 pool-1-thread-1开始执行Wed Oct 17 18:02:46 CST 2018
线程 pool-1-thread-3开始执行Wed Oct 17 18:02:46 CST 2018
DaoTest [name=dan, age=18, phone=null, addr=xiaoshuo, id=2]
线程 pool-1-thread-3结束执行Wed Oct 17 18:02:50 CST 2018
线程 pool-1-thread-3开始执行Wed Oct 17 18:02:50 CST 2018
DaoTest [name=null, age=null, phone=null, addr=null, id=null]
线程 pool-1-thread-1结束执行Wed Oct 17 18:02:50 CST 2018
线程 pool-1-thread-1开始执行Wed Oct 17 18:02:50 CST 2018
DaoTest [name=ning, age=1, phone=null, addr=phone, id=1]
线程 pool-1-thread-2结束执行Wed Oct 17 18:02:50 CST 2018
DaoTest [name=nihao, age=33, phone=null, addr=phone, id=4]
线程 pool-1-thread-1结束执行Wed Oct 17 18:02:54 CST 2018
DaoTest [name=ning是, age=3, phone=null, addr=phone, id=3]
线程 pool-1-thread-3结束执行Wed Oct 17 18:02:54 CST 2018
如果有问题欢迎联系我。
这里还有个问题,当我们需要返回参数的时候,通常存在容器中,如何返回给前端正确的返回值呢?留个问题之后在更新。