之前一直没有用过多线程,这次,写了一个多线程查询数据库的案列,并且比较一下多线程和单线程直接执行的效率,体会一下多线程同步。数据库中大概有1 W条数据。下面是核心代码:
单线程一次查询数据库
TestServiceImpl类
@Override
public List<Store> queryStoresInfo() {
return testDao.queryStoresInfo();
}
单线程For循环查询数据库
TestServiceImpl类
@Override
public List<Store> queryStoresInfoByFor() {
List<Store> lists = new ArrayList<>();
for (int i = 0; i < 10; i++) {
List<Store> list = testDao.queryStoresInfo();
lists.addAll(list);
}
return lists;
}
多线程查询数据库(使用join()进行同步)
TestServiceImpl类(下面这个是我的一个错误的做法)
将join写在循环内,实际本身还是一个串行的运行过程。
@Override
public List<Store> queryStoresInfoByThread() throws InterruptedException {
List<Store> lists = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(new TestThread(lists));
thread.start();
thread.join();
}
return lists;
}
TestServiceImpl类(正确的做法)
@Override
public List<Store> queryStoresInfoByThread() throws InterruptedException {
List<Store> lists = new ArrayList<>();
List<Thread> threads = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(new TestThread(lists));
thread.start();
threads.add(thread);
}
for (Thread thread: threads){
thread.join();
}
return lists;
}
TestThread类
public class TestThread implements Runnable {
TestDao testDao = SpringBeanUtils.getBean(TestDao.class);
private List<Store> stores;
public TestThread(List<Store> stores) {
this.stores = stores;
}
@Override
public void run() {
System.err.println(Thread.currentThread().getName() +" query data start...");
List<Store> store = testDao.queryStoresInfo();
synchronized (stores) {
stores.addAll(store);
}
System.err.println(Thread.currentThread().getName() +" query data end...");
}
}
多线程查询数据库(使用CountDownLatch进行同步)
TestServiceImpl类
@Override
public List<Store> queryStoresInfoByThread() throws InterruptedException {
List<Store> lists = new ArrayList<>();
CountDownLatch latch = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(new TestThread(lists, latch));
thread.start();
}
latch.await();
return lists;
}
TestThread类
public class TestThread implements Runnable {
TestDao testDao = SpringBeanUtils.getBean(TestDao.class);
private List<Store> stores;
private CountDownLatch latch;
public TestThread(List<Store> stores,CountDownLatch latch) {
this.stores = stores;
this.latch = latch;
}
@Override
public void run() {
System.err.println(Thread.currentThread().getName() +" query data start...");
List<Store> store = testDao.queryStoresInfo();
synchronized (stores) {
stores.addAll(store);
}
latch.countDown();
System.err.println(Thread.currentThread().getName() +" query data end...");
}
}
多线程查询数据库(使用线程池->CountDownLatch进行同步)
TestServiceImpl类
@Override
public List<Store> queryStoresInfoByThreadPool() {
ExecutorService executorService = new ThreadPoolExecutor(5, 10, 1, TimeUnit.MINUTES,new ArrayBlockingQueue<Runnable>(10));
List<Store> resultList = new ArrayList<>();
CountDownLatch latch = new CountDownLatch(10);
for (int i = 0; i < 10; i++) {
executorService.execute(new TestThread(resultList,latch));
}
executorService.shutdown();
try {
latch.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
return resultList;
}
TestThread类
public class TestThread implements Runnable {
TestDao testDao = SpringBeanUtils.getBean(TestDao.class);
private List<Store> stores;
private CountDownLatch latch;
public TestThread(List<Store> stores,CountDownLatch latch) {
this.stores = stores;
this.latch = latch;
}
@Override
public void run() {
System.err.println(Thread.currentThread().getName() +" query data start...");
List<Store> store = testDao.queryStoresInfo();
synchronized (stores) {
stores.addAll(store);
}
latch.countDown();
System.err.println(Thread.currentThread().getName() +" query data end...");
}
}
运行效率比较
single | for | Thread(join) | Thread(latch) | TheadPool |
---|---|---|---|---|
379 ms | 1124 ms | 544 ms | 596 ms | 507 ms |
379 ms | 1193 ms | 500 ms | 548 ms | 493 ms |