您的位置:首页 > 财经 > 产业 > 代运营是什么意思_中国建筑人才网下载_体彩足球竞彩比赛结果韩国比分_百度发布平台官网

代运营是什么意思_中国建筑人才网下载_体彩足球竞彩比赛结果韩国比分_百度发布平台官网

2025/4/28 17:16:00 来源:https://blog.csdn.net/no_rt_h_se_v_en/article/details/147401486  浏览:    关键词:代运营是什么意思_中国建筑人才网下载_体彩足球竞彩比赛结果韩国比分_百度发布平台官网
代运营是什么意思_中国建筑人才网下载_体彩足球竞彩比赛结果韩国比分_百度发布平台官网

一、线程基础:餐厅服务模型

场景类比
一家网红餐厅(Web服务器)有3位服务员(线程),同时为多个食客(客户端请求)服务
每个顾客的订单处理流程独立进行

核心属性表

模型要素程序映射实际开发意义
服务窗口Thread对象处理HTTP请求的独立单元
菜单任务Runnable实现类Servlet的service()逻辑
排队系统线程池(ThreadPool)Tomcat请求队列

二、线程创建的两种方式

1. Thread类继承(不推荐)
class OrderThread extends Thread {@Overridepublic void run() {// 处理订单逻辑(如数据库操作)}
}// Tomcat启动端口监听
new OrderThread().start();

缺点

  • 单继承限制
  • 每请求新建线程资源消耗大
2. Runnable接口实现(推荐)
class PaymentTask implements Runnable {@Overridepublic void run() {// 支付处理逻辑(第三方API调用)}
}// 提交到线程池执行
ExecutorService pool = Executors.newFixedThreadPool(5);
pool.submit(new PaymentTask());

优势

  • 资源复用(线程池)
  • 适合Servlet多请求处理:
// Servlet处理请求的伪代码
public class OrderServlet extends HttpServlet {public void doPost(HttpServletRequest req, HttpServletResponse resp) {Executor.submit(() -> processOrder(req)); // 异步处理}
}

程序检测示例

if (thread.getState() == Thread.State.TIMED_WAITING) {logger.info("订单处理超时,启动补偿流程");
}

四、线程中断的两种实践

1. 手动标志位控制
class AuditThread implements Runnable {private volatile boolean stopped = false; // 需volatile保证可见性void stopProcess() { stopped = true; }@Overridepublic void run() {while (!stopped) {// 审计日志分析(可能耗时)}}
}

应用场景

  • 后台定时任务(如每日对账)
  • 需优雅关闭的耗时操作
2. Interrupt机制示例
class MessageSender implements Runnable {@Overridepublic void run() {try {while (!Thread.currentThread().isInterrupted()) {sendMessage(); // 包含阻塞操作}} catch (InterruptedException e) {logger.warn("消息发送被终止");}}
}// 管理端触发停止
messageThread.interrupt();

中断触发情况

中断方式描述
sleep()/wait()抛出InterruptedException
正常执行中isInterrupted()标志置为true

五、线程协作(join/synchronized)

1. 并发订单处理问题
public class OrderService {private int stock = 100; // 共享资源// 问题代码:未同步导致超卖public void deductStock() {if(stock > 0) stock--; }
}

实际运行结果
可能多个线程同时判断stock>0导致负数

2. 同步解决方案对比
同步方式实现示例适用场景
synchronized方法级锁简单共享资源保护
Lock对象ReentrantLock需要灵活控制锁的释放
Atomic变量AtomicInteger安全计数单变量高并发

最佳实践

// 使用synchronized保证原子性
public synchronized void safeDeduct() {if(stock > 0) stock--;
}// 使用Atomic实现无需锁
private AtomicInteger atomicStock = new AtomicInteger(100);
public void atomicDeduct() {atomicStock.decrementAndGet();
}

六、Servlet中的多线程注意问题

典型场景

public class DangerServlet extends HttpServlet {// 危险!存在线程安全问题的成员变量private int counter = 0; protected void doGet(...) {counter++; // 竞争条件}
}

解决方案

  1. 同步控制
    synchronized (this) { counter++; }
    

  2. 改用局部变量
    // 每个请求独立变量
    int requestCounter = 0; 
    

  3. 原子工具类
    private AtomicInteger safeCounter = new AtomicInteger(0);
    safeCounter.incrementAndGet();
    

    七、知识应用案例

    火车站有 4个售票窗口,每个窗口都是一个独立线程,共同售 500张北京到上海的动车票,要求实现:
    ①不超卖(同一张票不能售多次)
    ②不卖空(没有0号票和负数票)

初始问题代码

public class TicketSystem {private int tickets = 500;public void sell() {if(tickets > 0) { // 模拟实际业务耗时try { Thread.sleep(20); } catch (Exception e) {}System.out.println(Thread.currentThread().getName() + " 售出: " + tickets--);} }public static void main(String[] args) {TicketSystem station = new TicketSystem();// 4个售票窗口竞争卖票for(int i=0; i<4; i++){new Thread(station::sell, "窗口"+(i+1)).start();}}
}

运行结果分析(问题展现)

错误情况1:重复售票

窗口1 售出: 500  
窗口3 售出: 500  
窗口4 售出: 499  
窗口2 售出: 498  
... 

原因:多个线程同时进入tickets > 0判断,导致多个窗口卖出同一号码的票

错误情况2:卖出0号票

窗口3 售出: 1  
窗口1 售出: 0 // ⚠️非法票号
窗口4 售出: -1 // ⚠️灾难

原因tickets--操作分为读取、计算、写入三步,中间被其他线程打断

底层锁竞争机制图解

问题代码修正(同步优化)

public class TicketSystemFix {private int tickets = 500;private Object lock = new Object(); // 专用锁对象public void sell() {synchronized(lock) { // 通过锁包裹临界区if(tickets > 0) { try { Thread.sleep(20); } catch (Exception e) {}System.out.println(Thread.currentThread().getName() + " 售出: " + tickets--);}}}public static void main(String[] args) {TicketSystemFix station = new TicketSystemFix();for(int i=0; i<4; i++) {new Thread(station::sell, "[安全窗口" + (i+1) + "]").start();}}
}

修正后执行流程

正确的线程协作

[安全窗口1] 售出: 500  
[安全窗口3] 售出: 499  
[安全窗口2] 售出: 498  
[安全窗口4] 售出: 497  
...
[安全窗口4] 售出: 1  // 最后一张,停止售票

关键现象

  1. 输出票号严格递减无重复
  2. 当窗口1持有锁,其余窗口的售票机显示"请稍候…"(即BLOCKED状态)

阻塞细节与性能平衡

现实场景中锁的权衡

假设每个卖票操作需要:业务处理20ms(CPU占用)+ 数据库提交100ms(IO等待)

同步代码优化调整

public void sellOptimized() {// 只同步数据修改部分,缩减锁范围int current; synchronized(lock) {if(tickets <= 0) return;current = tickets--;  // 原子操作缩减到一行}// 异步处理耗时IO(不持有锁)processPayment(current); // 支付验证(耗时100ms)printTicket(current);    // 出票(耗时20ms)
}

效果对比

指标全同步部分同步
吞吐量10票/秒250票/秒
CPU利用率30%(受限锁争用)

85%(高效)

知识点总结

  1. 锁的本质:内存中的一个标记位,控制代码段的独占访问权
  2. 阻塞代价:被阻塞的线程会进入内核等待队列,上下文切换开销≈1-2微秒
  3. 使用原则
    - ✅同步核心数据变更
    - ❌避免在锁内执行跨网络调用等长时操作

在JavaEE开发中,这种同步机制广泛用于:

  • Servlet共享Session管理
  • 数据库连接池分配
  • 缓存雪崩保护(限流)
    理解这些基础将帮助您在Spring框架中更好地使用@Transactional等线程敏感注解。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com