当前位置: 首页 > news >正文

如何在腾讯云建设网站jsp简单的网站开发例子

如何在腾讯云建设网站,jsp简单的网站开发例子,wordpress导航改哪个php文件,win 无法卸载 wordpress题图来自APOD 你好#xff0c;这里是codetrend专栏“高并发编程基础”。 引言 在并发执行任务时#xff0c;由于资源共享的存在#xff0c;线程安全成为一个需要考虑的问题。与串行化程序相比#xff0c;并发执行可以更好地利用CPU计算能力#xff0c;提高系统的吞吐量… 题图来自APOD 你好这里是codetrend专栏“高并发编程基础”。 引言 在并发执行任务时由于资源共享的存在线程安全成为一个需要考虑的问题。与串行化程序相比并发执行可以更好地利用CPU计算能力提高系统的吞吐量。 例如当B客户提交一个业务请求时不需要等到A客户处理结束才能开始这样可以提升用户体验。 然而并发编程也带来了新的挑战。无论是互联网系统还是企业级系统在追求高性能的同时稳定性也是至关重要的。开发人员需要掌握高效编程的技巧以确保程序在安全的前提下能够高效地共享数据。 共享资源指多个线程同时对同一份资源进行读写操作这就需要保证多个线程访问到的数据是一致的即数据同步或资源同步。为了实现安全且高效的共享数据以下是一些常用的方法和技术 使用锁Lock通过使用锁机制只有获得锁的线程才能访问共享资源其他线程需要等待锁的释放。常见的锁包括synchronized关键字、ReentrantLock等。锁机制可以保证共享资源在同一时间只被一个线程访问从而避免数据竞争和不一致的问题。使用同步块Synchronized Block通过在代码块前加上synchronized关键字确保同一时间只有一个线程可以执行该代码块。这样可以限制对共享资源的访问保证数据的一致性。使用原子操作类Atomic ClassesJava提供了一系列原子操作类如AtomicInteger、AtomicLong等它们可以保证针对共享资源的操作是原子性的不会被其他线程中断从而避免了数据不一致的问题。使用并发集合Concurrent CollectionsJava提供了一些并发安全的集合类如ConcurrentHashMap、ConcurrentLinkedQueue等它们在多线程环境下可以安全地进行读写操作避免了手动处理同步和锁的麻烦。使用线程安全的设计模式在程序设计阶段可以采用一些线程安全的设计模式如不可变对象、线程本地存储(Thread-local Storage)等来避免共享资源的竞争和冲突。 数据不一致的问题 package engineer.concurrent.battle.abasic;/*** 叫号机排队模拟通过多线程并发*/ public class TicketWindow extends Thread {private final String name;private final static int MAX 100;private static int ticket 1;public TicketWindow(String name) {this.name name;}public void run() {while (ticket MAX) {System.out.println(name 柜台正在排队排队号码为 ticket);ticket;}}public static void main(String[] args) {new TicketWindow(一号窗口).start();new TicketWindow(二号窗口).start();new TicketWindow(三号窗口).start();new TicketWindow(四号窗口).start();} }可能的输出结果如下 三号窗口柜台正在排队排队号码为1 四号窗口柜台正在排队排队号码为1 四号窗口柜台正在排队排队号码为3 三号窗口柜台正在排队排队号码为2 四号窗口柜台正在排队排队号码为7 ... 四号窗口柜台正在排队排队号码为101 四号窗口柜台正在排队排队号码为102其中 ticket 就是共享资源多个TicketWindow运行多线程竞争共享资源。可能出现的问题如下。 ticket 被重复使用也就是一个号被多个窗口叫到。ticket 超过最大限制也就是实际没得这个号但是却叫号了。ticket 没有被使用也就是一张号没有被叫到。 下面的实例代码是叫号机排队模拟通过多线程并发使用synchronized解决资源共享问题 package engineer.concurrent.battle.esafe;import java.util.concurrent.TimeUnit;/*** 叫号机排队模拟通过多线程并发使用synchronized解决资源共享问题*/ public class TicketWindowSynchronized implements Runnable {private final static int MAX 100;private static Integer ticket 1;private static final Object lockObj new Object();public void run() {while (ticket MAX) {synchronized (lockObj) {if (ticket MAX) { // 额外的判断System.out.println(Thread.currentThread() 柜台正在排队排队号码为 ticket);ticket;}}try {TimeUnit.MILLISECONDS.sleep(100);} catch (InterruptedException e) {throw new RuntimeException(e);}}}public static void main(String[] args) {TicketWindowSynchronized ticketTask new TicketWindowSynchronized();new Thread(ticketTask, 一号窗口).start();new Thread(ticketTask, 二号窗口).start();new Thread(ticketTask, 三号窗口).start();new Thread(ticketTask, 四号窗口).start();} }使用同步块Synchronized Block 在Java中同步块Synchronized Block是一种用于实现线程同步的机制。它用于标记一段代码确保在同一时间只有一个线程可以执行这段代码以避免数据竞争和并发问题。synchronized 字段可以用于对象方法、代码块中。 同步实例方法 public synchronized void synchronizedMethod() {// 执行需要同步的代码 }在实例方法上使用synchronized关键字将整个方法体标记为同步块。当一个线程进入同步方法时它将获取该实例对象的锁并且其他线程将被阻塞等待锁的释放。 同步静态方法 public static synchronized void synchronizedStaticMethod() {// 执行需要同步的代码 }在静态方法上使用synchronized关键字将整个静态方法标记为同步块。与同步实例方法类似当一个线程进入同步静态方法时它将获取类对象的锁并且其他线程将被阻塞等待锁的释放。 同步块 synchronized (lockObj) {// 执行需要同步的代码 }使用synchronized关键字结合一个对象来创建同步块。当一个线程进入同步块时它将获取该对象的锁并且其他线程将被阻塞等待锁的释放。在同步块内只有一个线程可以执行被同步的代码。 同步块中的条件等待和唤醒 synchronized (lockObj) {while (!conditionMet) {try {lockObj.wait(); // 条件不满足时线程进入等待状态并释放锁} catch (InterruptedException e) {// 处理中断异常}}// 执行需要同步的代码 }synchronized (lockObj) {conditionMet true; // 修改条件lockObj.notify(); // 唤醒一个等待的线程lockObj.notifyAll(); // 唤醒所有等待的线程 }在同步块中使用对象的wait()方法让线程进入等待状态并释放锁。当某个条件满足时可以使用notify()或notifyAll()方法唤醒等待的线程。注意在使用条件等待和唤醒时需要确保线程在同一对象上等待和唤醒。 同步块提供了一种简单的方式来实现线程同步通过获取对象的锁来保证同一时间只有一个线程可以执行同步块内的代码。这对于控制并发访问共享资源非常有用。但是需要注意如果多个线程竞争相同的锁可能会导致性能问题和死锁情况的发生。因此在使用同步块时需要仔细考虑锁的粒度和设计。 测试代码如下 package engineer.concurrent.battle.esafe; public class SynchronizedCounter {private int c 0;public synchronized void increment() {System.out.println(Thread.currentThread());;c;}public synchronized void decrement() {c--;}public synchronized int value() {return c;} }package engineer.concurrent.battle.esafe;import java.util.concurrent.CountDownLatch;public class SynchronizedCounterTest {public static void main(String[] args) throws InterruptedException {SynchronizedCounter counter new SynchronizedCounter();CountDownLatch countDownLatch new CountDownLatch(1000);for (int i 0; i 1000; i) {new Thread(() - {for (int j 0; j 100; j) {counter.increment();}countDownLatch.countDown();},线程编号i).start();}countDownLatch.await();System.out.println(counter.value());} }输出结果如下 100000使用锁Lock 在Java中锁Lock是一种用于实现线程同步的机制。它可以确保在同一时间只有一个线程可以访问共享资源以避免数据竞争和并发问题。与传统的synchronized关键字相比Lock提供了更大的灵活性和功能。使用锁Lock机制可以更细粒度地控制线程同步并且提供了更多高级功能例如可中断的锁获取、定时锁获取和条件变量等待。这使得锁成为Java中多线程编程的重要组件之一。 创建Lock对象 Lock lock new ReentrantLock();获取锁 lock.lock(); // 如果锁可用获取锁否则等待锁的释放或者带有超时设置的获取锁 boolean acquired lock.tryLock(5, TimeUnit.SECONDS); // 尝试在指定时间内获取锁返回是否成功获取锁 if (acquired) {try {// 执行需要同步的代码} finally {lock.unlock(); // 释放锁} } else {// 获取锁失败的处理逻辑 }释放锁 lock.unlock(); // 释放锁使用锁进行同步 lock.lock(); try {// 执行需要同步的代码 } finally {lock.unlock(); }使用锁的Condition进行条件等待和唤醒 Condition condition lock.newCondition();// 等待条件满足 lock.lock(); try {while (!conditionMet) {condition.await(); // 等待条件满足并释放锁}// 执行需要同步的代码 } catch (InterruptedException e) {// 处理中断异常 } finally {lock.unlock(); }// 唤醒等待的线程 lock.lock(); try {condition.signal(); // 唤醒一个等待的线程condition.signalAll(); // 唤醒所有等待的线程 } finally {lock.unlock(); }测试代码如下 package engineer.concurrent.battle.esafe;import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;public class SynchronizedCounter3 {private int c 0;Lock lock new ReentrantLock();public void increment() {lock.lock();System.out.println(Thread.currentThread());c;lock.unlock();}public void decrement() {lock.lock();c--;lock.unlock();}public int value() {return c;} }package engineer.concurrent.battle.esafe;import java.util.concurrent.CountDownLatch;public class SynchronizedCounter3Test {public static void main(String[] args) throws InterruptedException {SynchronizedCounter3 counter new SynchronizedCounter3();CountDownLatch countDownLatch new CountDownLatch(10000);for (int i 0; i 10000; i) {new Thread(() - {for (int j 0; j 100; j) {counter.increment();}countDownLatch.countDown();},线程编号i).start();}countDownLatch.await();System.out.println(counter.value());} }输出结果如下在并发情况下输出一致 100000使用原子操作类Atomic Classes 在Java中原子操作类Atomic Classes是一组线程安全的工具类用于进行原子性操作。它们提供了一些原子操作可以确保在多线程环境下对共享变量的操作是原子的不会出现数据竞争和并发问题。原子操作类提供了一些常见的原子操作方法可以确保对共享变量的操作是原子的。它们适用于高并发场景并且性能较好。使用原子操作类可以避免使用锁带来的开销并且能够简化线程同步的代码逻辑。 需要注意的是虽然原子操作类可以保证单个操作的原子性但不能保证多个操作的原子性。如果需要进行复合操作例如读取-修改-写入操作仍然需要使用锁或其他同步机制来保证原子性。另外原子操作类在某些情况下可能会存在ABA问题需要根据具体场景选择合适的解决方案。 AtomicBoolean AtomicBoolean atomicBoolean new AtomicBoolean();boolean currentValue atomicBoolean.get(); // 获取当前值atomicBoolean.set(true); // 设置新值boolean oldValue atomicBoolean.getAndSet(false); // 先获取当前值再设置新值并返回旧值AtomicInteger AtomicInteger atomicInteger new AtomicInteger();int currentValue atomicInteger.get(); // 获取当前值atomicInteger.set(10); // 设置新值int oldValue atomicInteger.getAndSet(5); // 先获取当前值再设置新值并返回旧值int newValue atomicInteger.incrementAndGet(); // 原子地增加1并返回新值int updatedValue atomicInteger.updateAndGet(x - x * 2); // 使用lambda表达式更新值并返回更新后的值AtomicLong AtomicLong atomicLong new AtomicLong();long currentValue atomicLong.get(); // 获取当前值atomicLong.set(100L); // 设置新值long oldValue atomicLong.getAndSet(50L); // 先获取当前值再设置新值并返回旧值long newValue atomicLong.incrementAndGet(); // 原子地增加1并返回新值long updatedValue atomicLong.updateAndGet(x - x * 2); // 使用lambda表达式更新值并返回更新后的值AtomicReference AtomicReferenceString atomicReference new AtomicReference();String currentValue atomicReference.get(); // 获取当前值atomicReference.set(Hello); // 设置新值String oldValue atomicReference.getAndSet(World); // 先获取当前值再设置新值并返回旧值boolean updated atomicReference.compareAndSet(World, Java); // 原子地比较和设置值返回是否成功更新测试代码如下 package engineer.concurrent.battle.esafe;import java.util.concurrent.atomic.AtomicInteger;public class SynchronizedCounter2 {private AtomicInteger c new AtomicInteger(0);public synchronized void increment() {System.out.println(Thread.currentThread());c.incrementAndGet();}public void decrement() {c.decrementAndGet();}public int value() {return c.get();} }package engineer.concurrent.battle.esafe;import java.util.concurrent.CountDownLatch;public class SynchronizedCounter2Test {public static void main(String[] args) throws InterruptedException {SynchronizedCounter2 counter new SynchronizedCounter2();CountDownLatch countDownLatch new CountDownLatch(1000);for (int i 0; i 1000; i) {new Thread(() - {for (int j 0; j 100; j) {counter.increment();}countDownLatch.countDown();},线程编号i).start();}countDownLatch.await();System.out.println(counter.value());} }输出结果如下在并发情况下输出一致 100000使用并发集合Concurrent Collections 在Java中有一组并发集合Concurrent Collections可以用于在多线程环境下安全地操作共享数据。这些集合类提供了线程安全的操作并且能够处理高并发的情况常用于多线程编程和并发控制。并发集合提供了一些常见的数据结构和操作方法能够在多线程环境下安全地进行读写操作。它们采用了特定的并发控制策略以提供高效的线程安全性能。需要根据具体的场景选择合适的并发集合类以满足线程安全和并发控制的需求。 需要注意的是并发集合并不适用于所有情况。在某些场景下例如需要保持原子性操作或依赖复合操作的情况下可能需要使用其他的同步机制来确保线程安全性。此外虽然并发集合可以提供更好的性能和扩展性但在某些情况下可能会占用更多的内存需要根据具体情况进行权衡和选择。 ConcurrentHashMap ConcurrentHashMapString, Integer map new ConcurrentHashMap();map.put(key1, 1); // 插入键值对int value map.get(key1); // 获取指定键的值boolean containsKey map.containsKey(key2); // 检查是否包含指定的键Integer oldValue map.putIfAbsent(key1, 2); // 当键不存在时才插入新值map.remove(key1); // 移除指定键的键值对ConcurrentLinkedQueue ConcurrentLinkedQueueString queue new ConcurrentLinkedQueue();queue.add(item1); // 添加元素到队列String head queue.peek(); // 获取队列头部元素String removedItem queue.poll(); // 移除并返回队列头部元素CopyOnWriteArrayList CopyOnWriteArrayListString list new CopyOnWriteArrayList();list.add(item1); // 添加元素到列表String item list.get(0); // 获取指定索引处的元素list.set(0, newItem); // 替换指定索引处的元素boolean removed list.remove(item1); // 移除指定元素ConcurrentSkipListMap ConcurrentSkipListMapInteger, String map new ConcurrentSkipListMap();map.put(1, value1); // 插入键值对Integer key map.firstKey(); // 获取第一个键String value map.get(key); // 根据键获取值map.remove(key); // 移除指定键的键值对测试代码如下 package engineer.concurrent.battle.esafe; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap;public class SynchronizedCounter5 {private ConcurrentMapString, Integer counter new ConcurrentHashMap();private final String key threadName;public void increment() {counter.compute(key, (key, value) - (value null) ? 1 : value 1);}public void decrement() {counter.compute(key, (key, value) - (value ! null value 0) ? value - 1 : 0);}public int value() {return counter.values().stream().mapToInt(Integer::intValue).sum();} }package engineer.concurrent.battle.esafe;import java.util.concurrent.CountDownLatch;public class SynchronizedCounterTest5 {public static void main(String[] args) throws InterruptedException {SynchronizedCounter5 counter new SynchronizedCounter5();CountDownLatch countDownLatch new CountDownLatch(1000);for (int i 0; i 1000; i) {new Thread(() - {for (int j 0; j 100; j) {counter.increment();}countDownLatch.countDown();},线程编号i).start();}countDownLatch.await();System.out.println(counter.value());} }输出结果如下在并发情况下输出一致 100000死锁原因和分析 死锁的产生 因为线程中锁的加入和线程同步到需求存在资源的竞争问题解决了但问题出现在解决办法也就是锁的不合理使用会导致死锁的出现。死锁是多线程编程中常见的问题指两个或多个线程因为互相持有对方需要的锁而陷入了无限等待的状态。Java中的死锁通常发生在如下情况下 竞争有限资源多个线程同时竞争一些有限的资源例如数据库连接、文件句柄等。锁嵌套一个线程持有一个锁尝试获取另一个锁而另一个线程持有第二个锁并尝试获取第一个锁。 下面是一个造成死锁的示例代码 /*** 在示例代码中两个线程分别持有 lock1 和 lock2并尝试获取对方持有的锁。如果这两个线程同时运行就会发生死锁因为它们互相持有了对方需要的锁。*/ public class DeadlockExample {static Object lock1 new Object();static Object lock2 new Object();public static void main(String[] args) {Thread t1 new Thread(() - {synchronized (lock1) { // 获取 lock1System.out.println(Thread 1: Holding lock 1...);try {Thread.sleep(10);} catch (InterruptedException e) {}synchronized (lock2) { // 尝试获取 lock2System.out.println(Thread 1: Holding lock 1 2...);}}},线程001);Thread t2 new Thread(() - {synchronized (lock2) { // 获取 lock2System.out.println(Thread 2: Holding lock 2...);try {Thread.sleep(10);} catch (InterruptedException e) {}synchronized (lock1) { // 尝试获取 lock1System.out.println(Thread 2: Holding lock 1 2...);}}},线程002);t1.start();t2.start();} }死锁的分析 通过jdk提供的开箱即用工具可以快速定位问题。以下是DeadlockExample产生死锁的定位过程。 使用 jps 查看当前进程的pid。 jps 20580 Launcher 44712 RemoteMavenServer36 12428 Jps 14556 25052 DeadlockExample使用 jstack pid命令分析堆栈信息。输出结果如下。 Found one Java-level deadlock:线程001:waiting to lock monitor 0x0000019d2d1eb820 (object 0x0000000713cfa108, a java.lang.Object),which is held by 线程002线程002:waiting to lock monitor 0x0000019d2d1eb740 (object 0x0000000713cfa0f8, a java.lang.Object),which is held by 线程001Java stack information for the threads listed above:线程001:at engineer.concurrent.battle.esafe.DeadlockExample.lambda$main$0(DeadlockExample.java:20)- waiting to lock 0x0000000713cfa108 (a java.lang.Object)- locked 0x0000000713cfa0f8 (a java.lang.Object)at engineer.concurrent.battle.esafe.DeadlockExample$$Lambda$14/0x0000000800c01200.run(Unknown Source)at java.lang.Thread.run(java.base17.0.7/Thread.java:833) 线程002:at engineer.concurrent.battle.esafe.DeadlockExample.lambda$main$1(DeadlockExample.java:34)- waiting to lock 0x0000000713cfa0f8 (a java.lang.Object)- locked 0x0000000713cfa108 (a java.lang.Object)at engineer.concurrent.battle.esafe.DeadlockExample$$Lambda$15/0x0000000800c01418.run(Unknown Source)at java.lang.Thread.run(java.base17.0.7/Thread.java:833)Found 1 deadlock.上面的jstack信息清晰的给出了死锁的代码位置和线程名称。通过这两个信息可以定位到代码块进行对应问题的修复。 死锁的避免 要避免死锁可以采取以下策略 避免锁嵌套尽量减少锁嵌套的层数以避免死锁的发生。按固定顺序获取锁多个线程按照固定的顺序获取锁以避免交叉竞争造成的死锁。使用 tryLock() 方法tryLock() 方法可以尝试获取锁一段时间如果失败则放弃获取锁避免一直等待造成的死锁。使用 LockInterruptibly() 方法LockInterruptibly() 方法可以在等待锁的过程中响应中断信号避免无限等待造成的死锁。合理设计资源分配合理地划分和分配资源以避免资源争用和死锁的产生。 修改后的代码如下 package engineer.concurrent.battle.esafe;import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;/*** 使用 tryLock() 方法tryLock() 方法可以尝试获取锁一段时间如果失败则放弃获取锁避免一直等待造成的死锁。*/ public class DeadlockExampleFix {static Lock lock1 new ReentrantLock();static Lock lock2 new ReentrantLock();public static void main(String[] args) {Thread t1 new Thread(() - {if(lock1.tryLock()) { // 获取 lock1System.out.println(Thread 1: Holding lock 1...);try {Thread.sleep(10);} catch (InterruptedException e) {}if(lock2.tryLock()) { // 尝试获取 lock2System.out.println(Thread 1: Holding lock 1 2...);}}},线程001);Thread t2 new Thread(() - {if(lock2.tryLock()) { // 获取 lock2System.out.println(Thread 2: Holding lock 2...);try {Thread.sleep(10);} catch (InterruptedException e) {}if(lock1.tryLock()) { // 尝试获取 lock1System.out.println(Thread 2: Holding lock 1 2...);}}},线程002);t1.start();t2.start();} }输出结果如下 Thread 2: Holding lock 2... Thread 1: Holding lock 1...参考 《Java高并发编程详解多线程与架构设计》 关于作者 来自一线全栈程序员nine的探索与实践持续迭代中。欢迎关注公众号“雨林寻北”或添加个人卫星codetrend备注技术。
http://www.dnsts.com.cn/news/143325.html

相关文章:

  • 网站正在建设中界面设计官方网站搭建要多少钱
  • 万宁市住房和城乡建设厅网站博客建站程序
  • 电商网站开发怎么样网站建设询价公告
  • 学校网站建设需求分析wordpress泛解析
  • 广西南宁网站设计浙江网站设计 site
  • 聊城手机网站公司电话mysql asp网站
  • 网站建设虚拟空间产品策划书模板
  • 安庆市大观区城乡建设局网站服务器方面如何规划建设网站
  • 做课内教学网站软文推广文章范文
  • 网站源码风险电商网站建设哪好
  • 什么是指定网站的域名连城住房和城乡建设局门户网站
  • 简约手机网站源码石狮网站开发
  • wordpress4.8.1seo线上培训多少钱
  • 沂源做网站如何在解决方案中新建网站
  • 一个人做网站好做吗建立门派
  • 海安网站开发宣传片拍摄公司排名
  • 网站 被 抄袭金山专业做网站
  • 新开传奇网站发布网单职业苏州网站开发公司兴田德润放心
  • 网站建设套餐报价方案网站代码优化所有标签
  • 公司网站建设描述广州网页制作培训
  • 陕西网站建设企业网站做任务赚佣金
  • 成都公租房官方网站开发商交房必须具备的条件
  • 做行业导航网站企业网站的建设的功能定位
  • 高性能网站建设进阶指南 pdfwordpress 显示icp
  • 萧山做网站哪里找怎么做app网站ui原型
  • 成品网站 免费怎样在别人网站做加强链接
  • 昭平县建设局网站网站怎么申请域名
  • 山东做网站建设的好公司排名影视网站怎么建设
  • 网站设计资料免费平面设计模板网站
  • 网站建设公司南昌哪有那样的网站