关于JAVA编写的WEB程序多次并发访问数据库的问题
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于JAVA编写的WEB程序多次并发访问数据库的问题相关的知识,希望对你有一定的参考价值。
关于JAVA编写的WEB程序多次并发访问数据库的问题
我们有个实时报表页面会30秒刷新一次,该页面可能同时有100人开着。
旧的逻辑是该页面利用<meta http-equiv="refresh" content="30" />来控制刷新,后端bean执行select语句查询然后在bean里拼接html返回页面显示。这样的实现方法会不会对数据库加重负担?
我想到一个解决方式,就是用一个对象来定时执行select语句和拼接HTML,然后返回一个静态的变量,用页面bean去获取该静态变量。
不知道这样算解决问题么?或者有什么更好的解决办法?
旧的方案,每隔30秒的自动刷新保持不变。
后台查询业务可以设计成定时任务,请参考Timer或者quertz设计实现。保持没28秒刷新一次就可以满足前台对数据有效性的要求。
这样设计可以解决并发访问数据的情况,因为访问数据库的查询业务只有一个定时任务来实现。
希望对你有帮助本回答被提问者和网友采纳 参考技术B 这样经常刷新肯定对数据库有影响的,你这样是可行的,也可以放在缓存里面~~
编写高效的Java代码:常用的优化技巧之并发编程技巧
编写高效的Java代码:常用的优化技巧【三】之JVM调优
一、使用并发集合和原子变量来减少竞争
在多线程并发执行的场景中,如果多个线程同时访问同一个共享资源,就会出现竞争条件,这会导致数据不一致或者程序异常。因此,使用并发集合和原子变量来减少竞争是非常必要的。
1.1 并发集合
并发集合是Java提供的一种线程安全的集合框架,包括ConcurrentHashMap、ConcurrentLinkedQueue、CopyOnWriteArrayList等。它们在实现上使用了锁分段技术,不同的元素被分配到不同的段中,不同的段可以由不同的线程同时访问,从而实现高效的并发操作。
以ConcurrentHashMap为例,它是一个线程安全的哈希表,支持高效的并发访问。可以使用putIfAbsent()方法来向ConcurrentHashMap中添加元素。该方法会检查哈希表中是否已经存在对应的键值对,如果不存在则添加。该方法的具体实现如下:
public V putIfAbsent(K key, V value)
V v = map.get(key);
if (v == null)
v = map.putIfAbsent(key, value);
return v;
1.2 原子变量
原子变量是Java提供的一种线程安全的变量类型,可以保证对变量的操作是原子性的。常见的原子变量有AtomicInteger、AtomicLong、AtomicBoolean等。
以AtomicInteger为例,它可以用来替代int类型的变量,在多线程环境下保证线程安全。可以使用compareAndSet()方法来进行原子操作。该方法会比较当前的值是否等于预期值,如果相等则更新为新值。该方法的具体实现如下:
public final boolean compareAndSet(int expect, int update)
return unsafe.compareAndSwapInt(this, valueOffset, expect, update);
二、使用线程池和Future来提高并发性能
在高并发的场景中,使用线程池和Future来提高并发性能是非常必要的。
2.1 线程池
线程池是一个重要的并发编程工具,它可以重复利用已经创建的线程,避免频繁地创建和销毁线程所带来的开销。在Java中,可以使用ThreadPoolExecutor类来创建线程池。
下面是一个简单的线程池示例:
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < 100; i++)
final int taskIndex = i;
executorService.execute(() ->
// 执行任务
System.out.println("Task " + taskIndex + " executed.");
);
executorService.shutdown();
2.2 Future
Future是Java提供的一种异步编程工具,可以在执行耗时操作时返回一个Future对象,通过该对象可以获取操作结果。在高并发的场景中,使用Future可以提高代码的可读性和可维护性。
下面是一个简单的Future示例:
ExecutorService executorService = Executors.newFixedThreadPool(10);
Future<Integer> future = executorService.submit(() ->
// 执行耗时操作
return 1 + 2;
);
int result = future.get(); // 获取操作结果
System.out.println("Result: " + result);
executorService.shutdown();
三、避免使用阻塞调用和不必要的等待
在高并发的场景中,使用阻塞调用和不必要的等待会导致程序性能下降。因此,需要尽量避免使用阻塞调用和不必要的等待。
3.1 避免阻塞调用
在Java中,常见的阻塞调用有IO操作、synchronized关键字、Object.wait()等。可以使用NIO、Lock、Condition等代替这些阻塞调用,从而提高程序性能。
3.2 避免不必要的等待
在多线程并发执行的场景中,不必要的等待会导致程序性能下降。可以使用Lock和Condition来实现线程间的等待和通知。
下面是一个简单的Lock和Condition示例:
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
int count = 0;
Thread t1 = new Thread(() ->
lock.lock();
try
while (count == 0)
condition.await(); // 等待
System.out.println("Count: " + count);
catch (InterruptedException e)
e.printStackTrace();
finally
lock.unlock();
);
Thread t2 = new Thread(() ->
lock.lock();
try
count = 1;
condition.signal(); // 通知
finally
lock.unlock();
);
t1.start();
t2.start();
总结:
本文介绍了一些常用的并发编程技巧,包括使用并发集合和原子变量来减少竞争、使用线程池和Future来提高并发性能、避免使用阻塞调用和不必要的等待等。在实际应用中,可以根据具体需求选择合适的并发编程工具和技巧,从而提高程序的性能和可维护性。
编写高效的Java代码:常用的优化技巧【三】之JVM调优
以上是关于关于JAVA编写的WEB程序多次并发访问数据库的问题的主要内容,如果未能解决你的问题,请参考以下文章