首页 文章 精选 留言 我的

精选列表

搜索[Provider桥接],共6075篇文章
优秀的个人博客,低调大师

- C3P0连池DeadLock机制分析

1 问题 近期,刚上线不久的生产系统的数据库连接池 C3P0 (版本为0.9.5.2)突然报出 APPARENT DEADLOCK!!! 错误。 1.1 错误日志 错误日志如下。 com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@7cf60134 -- APPARENT DEADLOCK!!! Creating emergency threads for unassigned pending tasks! com.mchange.v2.async.ThreadPoolAsynchronousRunner$DeadlockDetector@7cf60134 -- APPARENT DEADLOCK!!! Complete Status: Managed Threads: 3 Active Threads: 3 Active Tasks: com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask@3ce7f8aa on thread: C3P0PooledConnectionPoolManager[identityToken->1hgepsj9u1w3a4je54sly0|70165722]-HelperThread-#1 com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask@17f3c7a1 on thread: C3P0PooledConnectionPoolManager[identityToken->1hgepsj9u1w3a4je54sly0|70165722]-HelperThread-#2 com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask@65dc473c on thread: C3P0PooledConnectionPoolManager[identityToken->1hgepsj9u1w3a4je54sly0|70165722]-HelperThread-#0 Pending Tasks: com.mchange.v2.resourcepool.BasicResourcePool$1DestroyResourceTask@744937e8 com.mchange.v2.resourcepool.BasicResourcePool$1DestroyResourceTask@77e8b363 com.mchange.v2.resourcepool.BasicResourcePool$1DestroyResourceTask@7eafacf0 com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask@79cde1be com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask@44067f18 com.mchange.v2.resourcepool.BasicResourcePool$ScatteredAcquireTask@76c7bf50 Pool thread stack traces: Thread[C3P0PooledConnectionPoolManager[identityToken->1hgepsj9u1w3a4je54sly0|70165722]-HelperThread-#0,5,main] java.net.SocketInputStream.socketRead0(Native Method) java.net.SocketInputStream.socketRead(SocketInputStream.java:116) java.net.SocketInputStream.read(SocketInputStream.java:171) java.net.SocketInputStream.read(SocketInputStream.java:141) oracle.net.ns.Packet.receive(Unknown Source) oracle.net.ns.DataPacket.receive(Unknown Source) oracle.net.ns.NetInputStream.getNextPacket(Unknown Source) oracle.net.ns.NetInputStream.read(Unknown Source) oracle.net.ns.NetInputStream.read(Unknown Source) oracle.net.ns.NetInputStream.read(Unknown Source) oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1099) oracle.jdbc.driver.T4CMAREngine.unmarshalSB1(T4CMAREngine.java:1070) oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:478) oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:213) oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:796) oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1031) oracle.jdbc.driver.T4CPreparedStatement.executeMaybeDescribe(T4CPreparedStatement.java:836) oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1124) oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3285) oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3329) oracle.jdbc.OracleDatabaseMetaData.getTables(OracleDatabaseMetaData.java:2471) com.mchange.v2.c3p0.impl.DefaultConnectionTester$1.activeCheckConnectionNoQuery(DefaultConnectionTester.java:84) com.mchange.v2.c3p0.impl.DefaultConnectionTester$3.activeCheckConnectionNoQuery(DefaultConnectionTester.java:182) com.mchange.v2.c3p0.impl.DefaultConnectionTester.activeCheckConnection(DefaultConnectionTester.java:275) com.mchange.v2.c3p0.AbstractConnectionTester.activeCheckConnection(AbstractConnectionTester.java:79) com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.testPooledConnection(C3P0PooledConnectionPool.java:504) com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.testPooledConnection(C3P0PooledConnectionPool.java:464) com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.refurbishIdleResource(C3P0PooledConnectionPool.java:436) com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask.run(BasicResourcePool.java:2211) com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:696) Thread[C3P0PooledConnectionPoolManager[identityToken->1hgepsj9u1w3a4je54sly0|70165722]-HelperThread-#1,5,main] java.net.SocketInputStream.socketRead0(Native Method) java.net.SocketInputStream.socketRead(SocketInputStream.java:116) java.net.SocketInputStream.read(SocketInputStream.java:171) java.net.SocketInputStream.read(SocketInputStream.java:141) oracle.net.ns.Packet.receive(Unknown Source) oracle.net.ns.DataPacket.receive(Unknown Source) oracle.net.ns.NetInputStream.getNextPacket(Unknown Source) oracle.net.ns.NetInputStream.read(Unknown Source) oracle.net.ns.NetInputStream.read(Unknown Source) oracle.net.ns.NetInputStream.read(Unknown Source) oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1099) oracle.jdbc.driver.T4CMAREngine.unmarshalSB1(T4CMAREngine.java:1070) oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:478) oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:213) oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:796) oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1031) oracle.jdbc.driver.T4CPreparedStatement.executeMaybeDescribe(T4CPreparedStatement.java:836) oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1124) oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3285) oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3329) oracle.jdbc.OracleDatabaseMetaData.getTables(OracleDatabaseMetaData.java:2471) com.mchange.v2.c3p0.impl.DefaultConnectionTester$1.activeCheckConnectionNoQuery(DefaultConnectionTester.java:84) com.mchange.v2.c3p0.impl.DefaultConnectionTester$3.activeCheckConnectionNoQuery(DefaultConnectionTester.java:182) com.mchange.v2.c3p0.impl.DefaultConnectionTester.activeCheckConnection(DefaultConnectionTester.java:275) com.mchange.v2.c3p0.AbstractConnectionTester.activeCheckConnection(AbstractConnectionTester.java:79) com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.testPooledConnection(C3P0PooledConnectionPool.java:504) com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.testPooledConnection(C3P0PooledConnectionPool.java:464) com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.refurbishIdleResource(C3P0PooledConnectionPool.java:436) com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask.run(BasicResourcePool.java:2211) com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:696) Thread[C3P0PooledConnectionPoolManager[identityToken->1hgepsj9u1w3a4je54sly0|70165722]-HelperThread-#2,5,main] java.net.SocketInputStream.socketRead0(Native Method) java.net.SocketInputStream.socketRead(SocketInputStream.java:116) java.net.SocketInputStream.read(SocketInputStream.java:171) java.net.SocketInputStream.read(SocketInputStream.java:141) oracle.net.ns.Packet.receive(Unknown Source) oracle.net.ns.DataPacket.receive(Unknown Source) oracle.net.ns.NetInputStream.getNextPacket(Unknown Source) oracle.net.ns.NetInputStream.read(Unknown Source) oracle.net.ns.NetInputStream.read(Unknown Source) oracle.net.ns.NetInputStream.read(Unknown Source) oracle.jdbc.driver.T4CMAREngine.unmarshalUB1(T4CMAREngine.java:1099) oracle.jdbc.driver.T4CMAREngine.unmarshalSB1(T4CMAREngine.java:1070) oracle.jdbc.driver.T4C8Oall.receive(T4C8Oall.java:478) oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:213) oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:796) oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1031) oracle.jdbc.driver.T4CPreparedStatement.executeMaybeDescribe(T4CPreparedStatement.java:836) oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1124) oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3285) oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3329) oracle.jdbc.OracleDatabaseMetaData.getTables(OracleDatabaseMetaData.java:2471) com.mchange.v2.c3p0.impl.DefaultConnectionTester$1.activeCheckConnectionNoQuery(DefaultConnectionTester.java:84) com.mchange.v2.c3p0.impl.DefaultConnectionTester$3.activeCheckConnectionNoQuery(DefaultConnectionTester.java:182) com.mchange.v2.c3p0.impl.DefaultConnectionTester.activeCheckConnection(DefaultConnectionTester.java:275) com.mchange.v2.c3p0.AbstractConnectionTester.activeCheckConnection(AbstractConnectionTester.java:79) com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.testPooledConnection(C3P0PooledConnectionPool.java:504) com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.testPooledConnection(C3P0PooledConnectionPool.java:464) com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.refurbishIdleResource(C3P0PooledConnectionPool.java:436) com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask.run(BasicResourcePool.java:2211) com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:696) Task com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask@65dc473c (in deadlocked PoolThread) failed to complete in maximum time 60000ms. Trying interrupt(). Task com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask@3ce7f8aa (in deadlocked PoolThread) failed to complete in maximum time 60000ms. Trying interrupt(). Task com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask@17f3c7a1 (in deadlocked PoolThread) failed to complete in maximum time 60000ms. Trying interrupt(). 上面的日志报出了 APPARENT DEADLOCK!!! 错误,然后输出了ThreadPoolAsynchronousRunner 的状态,包括线程数,当前正在处理的任务,队列中等待处理的任务,以及 ThreadPoolAsynchronousRunner 任务线程的堆栈。 1.2 配置 生产上的配置如下。 <bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" > <property name="driverClass" value="oracle.jdbc.driver.OracleDriver"></property> <property name="jdbcUrl" value="${datasource.jdbcUrl}"></property> <property name="user" value="${datasource.user}"></property> <property name="password" value="${datasource.pass}"></property> <property name="maxPoolSize" value="${datasource.maxPoolSize}"></property> <property name="maxIdleTime" value="180"></property> <property name="idleConnectionTestPeriod" value="60"></property> <property name="checkoutTimeout" value="30000"></property> </bean> 基本相当于使用默认配置。 1.3 初步判断 根据日志,C3P0判断其线程池(ThreadPoolAsynchronousRunner)中的任务出现死锁(DEADLOCK),此时线程处于检查空闲数据链接状态是否可用。单从日志字面暂时无法判断问题所在。 查阅了网上的资料,对此问题原因分析较少,绝大部分不甚了了。比较多的文章是尝试通过调整参数来避免问题的出现的帖子。 秉着 “知其所以然” 的态度,再加上一点点的好奇心,我翻阅了一下C3P0的代码,试图从中发现端倪。 2 C3P0的死锁(DeadLock)机制分析 2.1 C3P0类结构 为了后面展示代码的需要,先附上一个我整理的C3P0的类结构图,有助于我们分析问题时确定问题的位置。如果下面的图太小,可以点击这里浏览 c3p0类结构图 我们重点关注右下角的几个类。 2.2 ThreadPoolAsynchronousRunner线程池 在 C3P0PooledConnectionPoolManager 类在初始化时中创建了一个taskRunner,其类型为 ThreadPoolAsynchronousRunner , 是一个 C3P0 自定实现的线程池。 public final class C3P0PooledConnectionPoolManager{ ... ThreadPoolAsynchronousRunner taskRunner; ... private synchronized void _poolsInit() { ... this.taskRunner = createTaskRunner( num_task_threads, matt, timer, idStr + "-HelperThread" ); ... } ... private ThreadPoolAsynchronousRunner createTaskRunner( int num_threads, int matt /* maxAdministrativeTaskTime */, Timer timer, String threadLabel ) { ... out = new ThreadPoolAsynchronousRunner( num_threads, true, timer, threadLabel ); return out; ... } ... } ThreadPoolAsynchronousRunner 线程池被作为成员注入到多个对象之中,最终用于执行 BasicResourcePool 类中定义的 ScatteredAcquireTask, AcquireTask, RemoveTask, DestroyResourceTask, RefurbishCheckinResourceTask, AsyncTestIdleResourceTask 等任务。 我们来看一下 ThreadPoolAsynchronousRunner 的代码。 public final class ThreadPoolAsynchronousRunner implements AsynchronousRunner { ... TimerTask deadlockDetector = new DeadlockDetector(); ... public ThreadPoolAsynchronousRunner( int num_threads, boolean daemon, Timer sharedTimer, String threadLabel ) { this( num_threads, daemon, DFLT_MAX_INDIVIDUAL_TASK_TIME, DFLT_DEADLOCK_DETECTOR_INTERVAL, DFLT_INTERRUPT_DELAY_AFTER_APPARENT_DEADLOCK, sharedTimer, false, threadLabel ); } ... private ThreadPoolAsynchronousRunner( int num_threads, boolean daemon, int max_individual_task_time, int deadlock_detector_interval, int interrupt_delay_after_apparent_deadlock, Timer myTimer, boolean should_cancel_timer, String threadLabel ) { this.num_threads = num_threads; this.daemon = daemon; this.max_individual_task_time = max_individual_task_time; this.deadlock_detector_interval = deadlock_detector_interval; this.interrupt_delay_after_apparent_deadlock = interrupt_delay_after_apparent_deadlock; this.myTimer = myTimer; this.should_cancel_timer = should_cancel_timer; this.threadLabel = threadLabel; recreateThreadsAndTasks(); myTimer.schedule( deadlockDetector, deadlock_detector_interval, deadlock_detector_interval ); } ... } 可以看到, ThreadPoolAsynchronousRunner 线程池默认创建3个执行线程,并且创建了一个 死锁检测(DeadLockDetector) 的定时任务,默认情况下每10秒执行一次。 2.3 DeadLockDetector内部机制 public final class ThreadPoolAsynchronousRunner implements AsynchronousRunner { ... class DeadlockDetector extends TimerTask { LinkedList last = null; LinkedList current = null; public void run() { ... current = (LinkedList) pendingTasks.clone(); ... if ( current.equals( last ) ) { //System.err.println(this + " -- APPARENT DEADLOCK!!! Creating emergency threads for unassigned pending tasks!"); ... recreateThreadsAndTasks(); run_stray_tasks = true; } ... if (run_stray_tasks) { AsynchronousRunner ar = new ThreadPerTaskAsynchronousRunner( DFLT_MAX_EMERGENCY_THREADS, max_individual_task_time ); for ( Iterator ii = current.iterator(); ii.hasNext(); ) ar.postRunnable( (Runnable) ii.next() ); ar.close( false ); //tell the emergency runner to close itself when its tasks are complete last = null; } else last = current; ... 可以看到,DeadLockDetector是ThreadPoolAsynchronousRunner 的内部类,是一个默认每10秒执行一次的定时任务。其工作原理是定时检查任务队列(pendingTasks)中的任务,如果前后两次检查发现待执行的任务没有变化,就认为可能产生了死锁,并额外创建线程执行等待任务。 3 问题分析 3.1 线程等待 从代码中可以看出,APPARENT DEADLOCK!!!报错原因主要是ThreadPoolAsynchronousRunner线程池的中的等待任务队列在经过一定时长(默认10秒)前后没有变化。 结合问题日志。我们可以初步判断问题的原因,是由于某些任务(如日志中显示AsyncTestIdleResourceTask)执行过程中失去响应(超过60s没有收到响应),导致后续的任务长时间等待,进而报错。 3.2 具体分析 进而观察执行线程的堆栈,可以发现三个任务都在执行检测连接有效性时,向服务端发送请求数据后,Oracle数据库未返回响应,导致线程长时间等待。 由于此问题无法通过构造场景重现,只能猜测,产生这种原因可能是连接在服务端已经超时,由服务端主动关闭连接,但由于TCP协议断开连接需要完成4次握手,而服务端只完成了前两次握手,这样就导致了客户端可以发送消息但接收不到任何内容,长时间等待直到超时。 3.3 解决方案 根据以上分析,我认为问题是maxIdleTime(连接最大空闲时间)与idleConnectionTestPeriod(空闲检测周期)参数配置与数据库不匹配引起的。 根据DBA的建议,将maxIdleTime调整为30秒,将idleConnectionTestPeriod调整为10秒。 4 后续 调整完后系统稳定运行,至今未再报出同样的错误。 在查看资料的过程中,发现有与我类似的情况,请看这里。问题出在同一块代码,但现象与原因均与我不同。我并不认为这是C3P0的缺陷,而是具体环境上的配置没有相匹配。 我再说一点废话,C3P0中大量使用了synchronized关键字进行加锁,由于单例没有使用double-check,导致正常代码中大量加锁,在高并发下效率很低。因此,如果性能对系统较为重要,还是推荐大家使用HikariCP替换C3P0。

优秀的个人博客,低调大师

大模型生成:在“概率的混沌”与“工程的秩序”之间,搭建确定性之

当人们惊叹于大模型(LLM)的“博学”时,他们往往将其比作一个无所不知的“数字大脑”。但顶尖的AI应用开发者心里清楚:大模型本质上不是数据库,而是一台对海量人类知识进行高维压缩的“概率预测机”。 它不“知道”答案,它只是在庞大数学空间的连续统中,计算出下一个最有可能出现的Token。

优秀的个人博客,低调大师

土耳其股市数据踩坑记:itick Turkey Stock API 实际使用分享

做全球市场配置的朋友最近老问我土耳其股市的数据怎么拿。里拉这几年波动大,BIST(伊斯坦布尔证券交易所)反而成了不少宏观策略和新兴市场基金盯的池子。但说实话,土耳其市场的数据接口不像美股、A股那么好找,免费能用的更少。我自己试了一圈,最后用 itick 跑通了,这里把实际用法和踩过的坑记一下。

优秀的个人博客,低调大师

国内用 Claude Code 终于不用翻墙了:一行命令搞定,自动 DeepSeek

一行命令装好 Claude Code + JeecgBoot Skills + DeepSeek 接入,无需翻墙使用 Claude Code,支持 Windows /macOS/ Linux 全平台。 一行命令搞定 国内开发者用 Claude Code 一直有三道坎:注册要海外手机号、API 要翻墙、账号经常被封。 这里给一个一键脚本,自动配好 DeepSeek 接入(兼容 Anthropic 协议,国内直连不需要翻墙),按你的系统挑一条: macOS / Linux curl -fsSL https://www.qiaoqiaoyun.com/claude/install-claude-code.sh * bash Windows(PowerShell 里贴) irm https://www.qiaoqiaoyun.com/claude/boot.ps1 * iex 怎么用:3 步 1. 准备 DeepSeek API Key 去 platform.deepseek.com 申请一个 sk- 开头的 Key,账户里充几块钱(够用很久)。 2. 跑上面那条命令 脚本会自动装好这些(已装的自动跳过): Node.js 18+ Python 3.8+ Git Claude Code CLI(@anthropic-ai/claude-code) 9 个 JeecgBoot Skills(来自 gitee.com/jeecg/skills) 写入 DeepSeek 环境变量 中间提示 请输入 DeepSeek API Key 时,右键粘贴(输入不回显是正常的,安全防偷窥),回车继续。 实际跑下来 Windows 一气呵成(winget 不通时自动回退华为云镜像 MSI/exe): Linux 同样一行命令,完成后输出干净的组件清单: 3. 装完直接开聊 mkdir my-project && cd my-project claude ⚠️ Linux/Mac 装完如果 claude: command not found,先跑 source ~/.bashrc && claude,或者直接重开终端。Windows 装完原窗口就能用。 装完能做什么:一句话生成系统 JeecgBoot 的 9 个 Skills 已经一起装上了,进 claude 后直接一句话调用: "做一个仓库管理模块" → Java + Vue3 + SQL + 菜单权限(jeecg-codegen) "做一张员工表带部门下拉和入职日期" → Online 表单(jeecg-onlform) "按这张截图做一个询价单" → 设计器表单(jeecg-desform) "做一个三级审批:主管→经理→总监" → BPMN 流程(jeecg-bpmn) "本月各部门人均工资排名" → Online 报表(jeecg-onlreport) "销售数据柱状图,按地区分组" → 数据图表(jeecg-onlchart) "按这张截图做财务月报" → 积木报表(jimureport) "做一个销售数据全屏大屏" → 1920×1080 大屏(jimubi-bigscreen) "做一个日常运营看板" → 24 栅格看板(jimubi-dashboard) 后台模型走 DeepSeek V4-Pro,按 token 计费,国内电信 / 联通 / 移动直连 api.deepseek.com,延迟 < 100ms。

优秀的个人博客,低调大师

阿里云短信套餐包-最低3分2/条-短信码-短信群发平台

一、活动对象 1、阿里云官网注册的个人实名认证用户。其中,新老用户均可作为拼团活动的推荐者,但只有未购买过短信服务(即账号下无订单记录)的新用户方有资格参与拼团购买。 2、同一用户仅有一次参与拼团推荐或拼团购买指定云通信国内短信服务的机会。例如:同一用户使用不同账号作为推荐者参与本活动的,仅首个参与活动的账号可获赠;在阿里云官网已有消费的用户重新注册新账号参与拼团购买的,新老账号将被视为同一用户,不具有购买资格。 二、活动时间 2018年8月10日-2018年8月31日。 三、活动规则 1、活动期间,推荐者可推荐新用户通过活动专属页面购买指定云通信国内短信包,具体规格如下: 实例规格: ①5千条短信包价格:原价225元,活动价170元,单价0.034元/条 ②5万条短信包价格:原价2000元,活动价1650元,单价0.033元/条 ③50万条短信包价格:原价19000元,活动价16000元,单价0.032元/条 2、接受推荐的每一新用户通过活动专属页面,可以以上拼团价格购买1个指定短信包,每个用户仅限首笔订单购买一个套餐包。 3、用户应在15分钟内完成拼团订单的支付,否则订单将自动失效。 购买地址: https://promotion.aliyun.com/ntms/act/communication/aliyun-group/buy.html?group=cSdPIBfW7H

优秀的个人博客,低调大师

锁屏状态网络电话,Skype商务 iOS 版推重要功能更新

据外媒消息,微软今天宣布Skype商务iOS版有重大功能更新,将能在手机锁屏状态下接通Skype商务版电话。这受益于最新的iOS10版本,对第三方网络电话软件的功能优化带来的利好。 Skype商务版的前身,为办公即时通讯软件Lync 2013。这一应用为大公司员工提供内部的交流,远程电话会议和视频会议等提供移动办公解决方案。Skype商务的iOS版在去年的早些时候上线。 类似的网络电话应用并不少,国外有Messenger、WhatsApp和监控软件TrueCaller。国内的主流社交软件QQ、微信和阿里钉钉也在这方面有布局。但目前都并没有基于iPhone的系统做本地化的优化,尤其是在打进网络电话来的时候,系统操作并不好。 微软对Skype功能更新的技术更新来源于CallKit,这是 iOS10版本在网络电话上的优化工具。商务版的Skype目前也可以处理多任务的电话,在接听一个语音电话的同时,可以接入新的电话,或者把对方留言放入语音备忘录,这几乎跟电话的功能相当。 Skype团队的一个技术博客上表示,除了灵活处理多任务的语音电话,用户还可以在手机的历史通话记录里看到Skype的通话记录。这个功能对忙碌的商务人士来说,势必是另一个重大的便利。 当然,国内的移动办公软件仍只在大型集团使用,大部分的移动办公或语音电话都在微信里完成。阿里的移动办公应用钉钉在今年发布了多项功能更新,随着钉钉移动办公用户的增长,未来是否会上线Skype商务版的类似功能也值得期待。 本文转自d1net(转载)

资源下载

更多资源
Mario

Mario

马里奥是站在游戏界顶峰的超人气多面角色。马里奥靠吃蘑菇成长,特征是大鼻子、头戴帽子、身穿背带裤,还留着胡子。与他的双胞胎兄弟路易基一起,长年担任任天堂的招牌角色。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册