首页
学习
活动
专区
圈层
工具
发布

公司裁员时,老板嫌技术总监工资太高,直接让人走人,结果总监一走,研发部门立马瘫痪,项目全停摆。。

刚看到个贴子,说一家公司裁员时,老板嫌技术总监工资太高,直接让人走人。结果总监一走,研发部门立马瘫痪,项目全停摆,最后老板只能加倍工资把人请回来。

真是典型的“只算成本,不看价值”。网友有人笑老板“自食其果”,也有人说总监该趁机涨薪。但在我看来,这件事反映的不是谁输谁赢,而是很多老板普遍的短视思维——只看眼前省下的钱,却没看到系统背后依赖的能力。

一个真正懂管理的老板,应该知道:高薪往往买的是核心竞争力。技术不是人堆砌出来的,是经验与体系的积累。

说到底,职场的本质是“价值换价值”。尊重专业,舍得投入,企业才能走得远【备注:文末可领最新资料】

算法题:转换回调函数为 Promise 函数

在公司楼下便利店蹭了杯美式,昨晚十一点多还在看日志,脑子有点糊,但这事儿得讲清楚:老项目里到处是“回调地狱”,新同学一看就头大。你要说用 Java 呢,Promise 这个词更像 JS 的,可在 Java 里我们有个等价物——CompletableFuture。把回调适配成它,代码立马顺眼,链式也好写。

为什么要“转 Promise”

场景你们肯定见过:fetchUser(id, callback)这种老式异步接口,成功走onSuccess,失败走onError,一层套一层很容易乱。而CompletableFuture有返回值,能链式拼装,还能超时、组合、并发汇聚,异常也统一处理,写起来清爽很多。

一个通用的“promisify”适配器

我先写了两个小型函数式接口,描述“如何注册回调”和“如果支持取消该怎么取消”。然后给出两个适配器:基础版和可取消版。直接贴代码,你们自己抄走用就行。

import java.util.concurrent.*;

import java.util.concurrent.atomic.AtomicReference;

import java.util.function.*;

publicclass Promisify {

  // 老式回调接口

  publicinterface Callback<T> {

      void onSuccess(T value);

      void onError(Throwable error);

  }

  // 仅注册回调,不支持取消

  @FunctionalInterface

  publicinterface CbRegister<T> {

      void call(Callback<T> cb);

  }

  // 如果底层返回一个可取消句柄

  publicinterface Cancellable { void cancel(); }

  @FunctionalInterface

  publicinterface CancellableRegister<T> {

      Cancellable call(Callback<T> cb);

  }

  // 基础版:把“注册回调”的方式转成 CompletableFuture

  publicstatic <T> CompletableFuture<T> promisify(CbRegister<T> register) {

      CompletableFuture<T> future = new CompletableFuture<>();

      try {

          register.call(new Callback<T>() {

              @Overridepublic void onSuccess(T value) {

                  future.complete(value);

              }

              @Overridepublic void onError(Throwable error) {

                  future.completeExceptionally(error);

              }

          });

      } catch (Throwable t) {

          future.completeExceptionally(t);

      }

      return future;

  }

  // 可取消版:如果底层支持 cancel,则把 future.cancel(true) 传递下去

  publicstatic <T> CompletableFuture<T> promisify(CancellableRegister<T> register) {

      CompletableFuture<T> future = new CompletableFuture<>();

      AtomicReference<Cancellable> holder = new AtomicReference<>();

      try {

          Cancellable c = register.call(new Callback<T>() {

              @Overridepublic void onSuccess(T value) {

                  future.complete(value);

              }

              @Overridepublic void onError(Throwable error) {

                  future.completeExceptionally(error);

              }

          });

          holder.set(c);

      } catch (Throwable t) {

          future.completeExceptionally(t);

      }

      future.whenComplete((v, e) -> {

          if (future.isCancelled()) {

              Cancellable c = holder.get();

              if (c != null) c.cancel();

          }

      });

      return future;

  }

  // 小工具:给任意 future 加超时(不指定框架,纯 JDK)

  publicstatic <T> CompletableFuture<T> withTimeout(

          CompletableFuture<T> src, long timeout, TimeUnit unit, ScheduledExecutorService ses) {

      CompletableFuture<T> wrapped = new CompletableFuture<>();

      ScheduledFuture<?> timer = ses.schedule(

              () -> wrapped.completeExceptionally(new TimeoutException("timeout " + timeout + " " + unit)),

              timeout, unit);

      src.whenComplete((v, e) -> {

          if (e == null) wrapped.complete(v);

          else wrapped.completeExceptionally(e);

          timer.cancel(false);

      });

      // 取消向源头传递

      wrapped.whenComplete((v, e) -> {

          if (wrapped.isCancelled()) src.cancel(true);

      });

      return wrapped;

  }

}

旧接口如何套一层就“变 Promise”

假设你手里有个老 API:

// 旧式异步:成功/失败走回调

interface LegacyUserService {

  void fetchUser(String id, Promisify.Callback<User> cb);

  // 或者返回可取消句柄:

  Promisify.Cancellable fetchAvatar(String id, Promisify.Callback<byte[]> cb);

}

那就这么用:

LegacyUserService service = ...;

// 基础回调 -> CompletableFuture

CompletableFuture<User> userF = Promisify.promisify(cb -> service.fetchUser("42", cb));

// 可取消的回调 -> CompletableFuture

CompletableFuture<byte[]> avatarF = Promisify.promisify(cb -> service.fetchAvatar("42", cb));

// 链式写法、异常统一处理、带超时

ScheduledExecutorService ses = Executors.newSingleThreadScheduledExecutor();

CompletableFuture<String> result =

  Promisify.withTimeout(userF, 2, TimeUnit.SECONDS, ses)

           .thenCombine(avatarF, (u, avatar) -> u.getName() + " / " + avatar.length)

           .exceptionally(e -> "兜底:" + e.getMessage());

第一,底层回调可能“多次触发”,务必保证只complete一次(CompletableFuture自己会忽略后续 complete,但你仍该查明根因)。第二,调用方取消时记得把取消往下传,不然线程池和 IO 还在干活儿,白白占资源。

行了我去热个包子。你把上面这个Promisify类丢到公共模块里,老回调世界基本就能和平演进到“类 Promise”写法了。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OwqG1rNCW18U60fXqUyE8AYw0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。
领券