相关文章推荐
细心的打火机  ·  請領(初補換)國民身分證·  3 月前    · 
伤情的凉茶  ·  云南师大附中2009届高考录取情况(不完全统 ...·  6 月前    · 
重情义的打火机  ·  2024常州文化旅游节新闻发布会实录·  1 年前    · 
奔跑的猴子  ·  美刊文章:普京是西方眼中的“谜中之谜”-新华网·  1 年前    · 
阳刚的雪糕  ·  MySQL中将11/17/2021 ...·  1 年前    · 
Code  ›  记一次unable to create new native thread错误处理过程 - 云+社区 -
线程 spring框架
https://cloud.tencent.com/developer/article/1366014
天涯
6 年前
菜单 腾讯云
备案 控制台
云+社区
  • 专栏
  • 问答
  • 沙龙
  • 快讯
  • 团队主页
  • 开发者手册
  • 智能钛AI
  • 在线学习中心
  • TVP
搜索
写文章 提问
登录 注册
展开

腾讯云·社区

登录

云+社区

  • 首页
  • 专栏
  • 问答
  • 沙龙
  • 快讯
  • 团队主页
  • 开发者手册
  • 智能钛AI
  • 在线学习中心
  • TVP
返回腾讯云官网

记一次unable to create new native thread错误处理过程

写文章

记一次unable to create new native thread错误处理过程

良辰美景TT 发表于 java、Spring、技术分享
1.3K
广告 关闭

11.11 智慧上云

云服务器企业新用户优先购,享双11同等价格

早上运维说线上出错了,发了如下截图:

错误截图

unable to create new native thread,看到这里,首先想到的是让运维搞一份线上的线程堆栈(可能通过jstack命令搞定的)。发现线上的堆栈竟然有5M多大,打开文件后线程数量居然达到了8000多个。有大量的线程堆栈如下图所示:

线程堆栈

。看到有大量的线程是以 scheduler- 开头的,可以确定的是程序里有使用spring的定时任务功能,定时的处理一些任务。会不会是有长时间的定时任务造成线程没有关闭。于是翻看了下spring 的配置文件。代码如下:

    <task:executor id="executor" pool-size="5" />
    <task:scheduler id="scheduler" pool-size="10" />
    <task:annotation-driven executor="executor" scheduler="scheduler" />

可以肯定的是这里有配置线程池,但是线程池的大小也就10个啊,怎么会有8000多个线程。看到这里,我差点去翻spring的源码,想看看是不是spring的bug。检查看发现通过task:scheduler启动的线程是以scheduler-命名的,并不会有后面的SendThread与EventThread。上面的堆栈还能看出线程与zookeeper有关。于是还是回到自已的代码中,(必竟自已的代码出问题的可能性还是比框架代码出问题的概率要高出一个量级的)。   服务是分布式部署的,各部署的机器能够提供对等的服务。对于有需要一台机器执行的任务便会用到分布式锁,而zookeeper是能够用来实现分布式锁的,代码如下:

/**
 * 基于zookeep实现的分布式锁
public class ZookeeperLock implements DistributedLock,Watcher{
    private String basePath;
    private ZooKeeper zk ;
    private String host;
    Logger logger = LoggerFactory.getLogger(ZookeeperLock.class);
    private final static String realIP =  IpUtils.getRealIp();
    public ZookeeperLock(String host,String basePath) {
        this.basePath = basePath;
        this.host = host;
    @Override
    public boolean getDistributedLock(String businessname) {
        if(StringUtils.isBlank(businessname)){
            throw new IllegalArgumentException("businessname can not be empty!!!");
        try {
            zk = new ZooKeeper(host, 3000, this);
            logger.info("success get zk:"+zk +"and host is:" + host);
        } catch (IOException e) {
            logger.error("error is IOException:" + e.getMessage());
        int retries=0;
        while(retries++ < 5){
            if(zk.getState() == States.CONNECTED ){
                String key =basePath + "/" + businessname + "_" +DateFormatUtils.format(new Date(), "yyMMdd") ;
                try {
                    if(zk.exists(key, false) == null){
                        zk.create(key, realIP.getBytes(), Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
                        logger.info("get distributed lock success! ip is " + realIP);
                        return true;
                } catch (KeeperException e) {
                    logger.error("error is KeeperException: " + e.getMessage());
                    releaseLock();
                } catch (InterruptedException e) {
                    logger.error("error is InterruptedException 1: " + e.getMessage());
                logger.debug("fail to get lock , interrupt the loop!");
                break;
            //仅在State状态不少Connected时才会循环多次等待zookeeper连接成功
            try {
                Thread.sleep(1000);
                logger.info("zookeeper client has not connected." + zk.getState());
            } catch (InterruptedException e) {
                logger.error("error is InterruptedException 2: " + e.getMessage());
        return false;
    @Override
    public void releaseLock() {
        if(zk != null){
            try {
                zk.close();
                zk = null;
            } catch (InterruptedException e) {
    public void process(WatchedEvent event) {
        logger.debug( " Zookeeper client connect success! The clent ip is " + realIP);
}

分布式锁原理: 1):往指定的目录创建临时节点,创建成功的成获取锁。 2):业务执行完成后,需要删除相应的临时节点,相当于释放锁。 代码提供了加锁与解锁的逻辑,通过ZookeeperLock 对象,便能够实现分布式锁了。ZookeeperLock通过xml文件的配置来进行初使化。 为了方便对ZookeeperLock 的使用,提供了相应的模版类,代码如下:

@Component 
public class ZookeeperLockTemplate {
    private static final Logger logger = LoggerFactory.getLogger(ZookeeperLockTemplate.class);
    @Autowired  //容器会自动注入
    private ZookeeperLock distributedLock;
    public void execute(String businessname, ZookeeperLockCallBack callBack){
        try {
            if (distributedLock.getDistributedLock(businessname)) {
                callBack.call();
        } catch (Exception e) {
            logger.error("ZookeeperLockTemplate error! ", e);
        } finally {
            distributedLock.releaseLock();
}

代码看上去并没有什么问题,但是问题就出在ZookeeperLockTemplate这个类上。 通过componet注解注释的类在Spring 容器里是单例的,里面的属性即使scope类型是prototype,每次使用的时候也是用的同一个实例 。上面的ZookeeperLockTemplate如果在多线程的情况下使用,便会有大的问题, 一个线程可能关闭另一个线程开启的锁,从而造成另一个线程的锁无法关闭,导制zk = new ZooKeeper(host, 3000, this)这个对象的线程一直在内存中 修改的方法也很简单,在execute方法里,每次都从spring IOC的容器里取一次就好了。   上面的代码如果有问题,那在线上应该能够频繁的重现,而不至于上线好久了才发现这样的问题。这里主要是因为线上就三个定时任务,而且定时任务执行的并不频繁,但是他们的执行时间是有重叠的(也就是有可能有多线程的情况)。从日子累计到8000多条线程也可以看出只有运行了一定时间后,才可能出现问题。

本文参与 腾讯云自媒体分享计划 ,欢迎正在阅读的你也加入,一起分享。

发表于 2018-11-21 2018-11-21 18:24:04
NAT 运维 Spring ZooKeeper 分布式
举报
1 0
分享
  • 分享文章到朋友圈

  • 分享文章到 QQ
  • 分享文章到微博
  • 复制文章链接到剪贴板

扫码关注云+社区

领取腾讯云代金券

java、Spring、技术分享

49 篇文章 13 人订阅
  • 数据结构--堆
  • 数据结构--线段树
  • java SSL
  • JMH基准测试
  • Spring集成TestNG测试MVC Controller

我来说两句

0 条评论
登录 后参与评论
  • 上一篇:linux内核调试技巧之一 dump_stack【转】
  • 下一篇:Conway生命游戏

相关文章

来自专栏 从零开始学自动化测试

appium+python自动化60-appium命令行参数

许多Appium 1.5服务器参数已被弃用,以支持—default-capabilities标志。

271 1 0
来自专栏 java思维导图

给你一份SpringBoot知识清单

在过去两三年的Spring生态圈,最让人兴奋的莫过于Spring Boot框架。或许从命名上就能看出这个框架的设计初衷:快速的启动Spring应用。因而Spri...

177 4 0
来自专栏 大魏分享(微信公众号:david-share)

JavaEE中资源注入松耦合的实现 | 从开发角度看应用架构13

上下文和依赖注入(CDI)规范是Java EE规范中的许多从属规范之一。虽然CDI是在Java EE 6中引入的,但CDI背后的概念已经出现在各种框架中,包括S...

115 2 0
来自专栏 CSDN技术头条

学 Spring Boot 看这个就够了!

在过去两三年的 Spring 生态圈,最让人兴奋的莫过于 Spring Boot 框架。Spring Boot 应用本质上就是一个基于 Spring 框架的应用...

2.5K 4 0
来自专栏 JAVA高级架构

2017 年你不能错过的 Java 类库

各位读者好, 这篇文章是在我看过 Andres Almiray 的一篇介绍文后,整理出来的。 因为内容非常好,我便将它整理成参考列表分享给大家, 同时附上各个库...

294 8 0
来自专栏 枕边书

从并发处理谈PHP进程间通信(二)System V IPC

前言

 
推荐文章
细心的打火机  ·  請領(初補換)國民身分證
3 月前
伤情的凉茶  ·  云南师大附中2009届高考录取情况(不完全统计二) | 已归档文章 | 云南师范大学附属中学
6 月前
重情义的打火机  ·  2024常州文化旅游节新闻发布会实录
1 年前
奔跑的猴子  ·  美刊文章:普京是西方眼中的“谜中之谜”-新华网
1 年前
阳刚的雪糕  ·  MySQL中将11/17/2021 11:38:30 AM转化为2021-17-11 11:38:30 - CSDN文库
1 年前
今天看啥   ·   Py中国   ·   codingpro   ·   小百科   ·   link之家   ·   卧龙AI搜索
删除内容请联系邮箱 2879853325@qq.com
Code - 代码工具平台
© 2024 ~ 沪ICP备11025650号