我目前正在尝试更多地利用 kotlin 协程。但我面临一个问题:在这些协程中使用 moshi 或 okhttp 时,我收到警告:
“不适当的阻塞方法调用”
解决这些问题的最佳方法是什么?我真的不想不合适;-)
在kotlinx.coroutines库中,您可以使用launch(with join)或async(with await)启动新的协同程序.他们之间有什么区别?
在本网站上为另一个答案编写代码时,我遇到了这样的特点:
static void testSneaky() {
final Exception e = new Exception();
sneakyThrow(e); //no problems here
nonSneakyThrow(e); //ERRROR: Unhandled exception: java.lang.Exception
}
@SuppressWarnings("unchecked")
static <T extends Throwable> void sneakyThrow(Throwable t) throws T {
throw (T) t;
}
static <T extends Throwable> void nonSneakyThrow(T t) throws T {
throw t;
}
Run Code Online (Sandbox Code Playgroud)
首先,我很困惑为什么sneakyThrow对编译器调用是好的.T在没有提到未经检查的异常类型的任何地方时,它推断出什么可能的类型?
其次,接受这是有效的,为什么编译器会在nonSneakyThrow电话中抱怨?它们看起来非常相像.
Kotlin协程可以用于生产,它们的实验状态意味着什么?
我的目标是在从Hibernate生成HTTP响应时实现O(1)空间复杂度ScrollableResults.我想保留MessageConverter调度a的标准机制来处理从a返回的对象@Controller.我已经设置了以下内容:
MappingJackson2HttpMessageConverter丰富了JsonSerializer处理Java 8的a Stream;ScrollableResultSpliterator包装需要ScrollableResults成Stream;OpenSessionInViewInterceptor需要保持Hibernate会话在MessageConverter;hibernate.connection.release_mode为ON_CLOSE;con.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT).另外,我需要一个支持这种可保持性的数据库.PostgreSQL就是这样一个数据库,我对此没有任何麻烦.
我遇到的最后一个绊脚石是HibernateTransactionManager事务提交所使用的策略:除非底层会话是"Hibernate管理的",否则它会disconnect()关闭我的光标以及其他所有内容.这样的策略在某些特殊情况下很有用,特别是"会话范围会话",这些会议远离我的要求.
我设法用一个糟糕的黑客解决这个问题:我不得不用一种方法来覆盖有问题的方法,该方法实际上是原始的复制粘贴,除了被移除的disconnect()调用,但它必须求助于反射来访问私有API.
public class NoDisconnectHibernateTransactionManager extends HibernateTransactionManager
{
private static final Logger logger = LoggerFactory.getLogger(NoDisconnectHibernateTransactionManager.class);
public NoDisconnectHibernateTransactionManager(SessionFactory sf) { super(sf); }
@Override
protected void doCleanupAfterCompletion(Object transaction) {
final JdbcTransactionObjectSupport txObject = (JdbcTransactionObjectSupport) transaction;
final Class<?> c = …Run Code Online (Sandbox Code Playgroud) 这个问题与我关于Java中现有协程实现的问题有关.如果我怀疑,事实证明Java中目前没有完整的协同程序实现,那么实现它们需要什么?
正如我在那个问题中所说,我知道以下内容:
我将依次解决每个人的不足之处.
这种"解决方案"是病态的.协同程序的重点是避免线程,锁定,内核调度等的开销.协同程序应该是轻量级的,并且只能在用户空间中执行.在具有严格限制的全倾斜螺纹方面实现它们可以消除所有优点.
这种解决方案更实用,虽然有点难以实现.这与在C中的协同程序库中跳转到汇编语言大致相同(这是其中有多少工作),其优点是您只有一个架构可以担心并且正确.
它还将您绑定到仅在完全兼容的JVM堆栈上运行代码(例如,没有Android),除非您可以找到在非兼容堆栈上执行相同操作的方法.但是,如果您确实找到了这样做的方法,那么您现在已经将系统复杂性和测试需求翻了一番.
达芬奇机器很酷的实验,但由于它不是标准的JVM,它的功能无处不在.事实上,我怀疑大多数生产环境都会特别禁止使用达芬奇机器.因此,我可以使用它来进行很酷的实验,但不能用于我期望发布到现实世界的任何代码.
这也有类似于上面的JVM字节码操作解决方案的附加问题:将无法在替代堆栈(如Android)上工作.
这个解决方案在Java中实现这一点的意义重大.CPU和操作系统的每种组合都需要独立测试,每一种都是可能令人沮丧的微妙故障.或者,当然,我可以完全将自己绑定到一个平台,但这也使得用Java做事的意义完全没有实际意义.
所以...
有没有办法在不使用这四种技术之一的情况下在Java中实现协同程序?或者我会被迫使用那些闻起来最少的四个中的一个(JVM操作)?
编辑添加:
只是为了确保混乱载,这是一个相关的问题我的另外一个,但又不尽相同.那个人正在寻找一个现有的实施方案,以避免不必要地重新发明轮子.这是一个问题,如果另一个证明无法解决,将如何在Java中实现协同程序.目的是在不同的线程上保留不同的问题.
在Java 8中使用FP习惯用法时,异常(尤其是已检查的异常)会严重中断程序逻辑的流程.以下是一个任意示例:
String s1 = "oeu", s2 = "2";
Stream.of(s1, s2).forEach(s ->
System.out.println(Optional.of(s).map(Integer::parseInt).get()));
Run Code Online (Sandbox Code Playgroud)
当不可解析的字符串出现异常时,上面的代码会中断.但是说我只想用默认值替换它,就像我可以用Optional:
Stream.of(s1, s2).forEach(s ->
System.out.println(Optional.of(s)
.map(Integer::parseInt)
.orElse(-1)));
Run Code Online (Sandbox Code Playgroud)
当然,这仍然失败因为Optional只处理nulls.我想要的东西如下:
Stream.of(s1, s2).forEach(s ->
System.out.println(
Exceptional.of(s)
.map(Integer::parseInt)
.handle(NumberFormatException.class, swallow())
.orElse(-1)));
Run Code Online (Sandbox Code Playgroud)
注意:这是一个自我回答的问题.
我正在读Kotlin Coroutine并知道它是基于suspend功能的.但是什么suspend意思呢?
协程或功能被暂停?
来自https://kotlinlang.org/docs/reference/coroutines.html
协同程序基本上是协程,可以在不阻塞线程的情况下暂停
我听说人们经常说"暂停功能".但是我认为正在等待函数完成的是协同程序被暂停?"暂停"通常意味着"停止操作",在这种情况下,协程是空闲的.
我们应该说协程被暂停吗?
哪个协程被暂停?
来自https://kotlinlang.org/docs/reference/coroutines.html
为了继续这个类比,await()可以是一个挂起函数(因此也可以从async {}块中调用),它挂起一个协同程序,直到完成一些计算并返回其结果:
async { // Here I call it the outer async coroutine
...
// Here I call computation the inner coroutine
val result = computation.await()
...
}
Run Code Online (Sandbox Code Playgroud)
它说"在完成某些计算之前暂停协程",但协同程序就像一个轻量级的线程.因此,如果协程被暂停,那么计算怎么办呢?
我们看到await被调用computation,所以它可能会async返回Deferred,这意味着它可以启动另一个协同程序
fun computation(): Deferred<Boolean> {
return async {
true
}
}
Run Code Online (Sandbox Code Playgroud)
引述说暂停协程.它是指suspend外部的asynccoroutine,还是suspend内部的computationcoroutine?
这suspend意味着当外部async协程正在wait(await …
我相信这里
final int i;
try { i = calculateIndex(); }
catch (Exception e) { i = 1; }
Run Code Online (Sandbox Code Playgroud)
i如果控制到达catch-block,则可能无法分配.但是,Java编译器不同意并声称the final local variable i may already have been assigned.
我还缺少一些细微之处,或者这只是Java语言规范用于识别潜在重新分配的模型的弱点?我的主要担心是这样的事情Thread.stop(),这可能会导致异常被"凭空捏造"抛出,但我仍然看不到它如何在赋值后抛出,这显然是try-block中的最后一个动作.
如果允许,上面的成语将使我的许多方法更简单.请注意,此用例具有一流的语言支持,例如Scala,它始终使用Maybe monad:
final int i = calculateIndex().getOrElse(1);
Run Code Online (Sandbox Code Playgroud)
我认为这个用例是一个非常好的动机,允许一个特殊情况 肯定i是在catch块中未分配.
经过一番思考后,我更加确定这只是JLS模型的一个弱点:如果我在所提出的例子中声明了公理,i当控制到达catch-block时肯定是未分配的",它将不会与任何其他公理冲突或定理.编译器i在catch块中分配之前不允许任何读取,因此i无法查看是否已分配的事实.
java ×6
java-8 ×4
kotlin ×4
coroutine ×2
async-await ×1
asynchronous ×1
cloneable ×1
deprecated ×1
final ×1
generics ×1
hibernate ×1
java-stream ×1
moshi ×1
okhttp ×1
spring-orm ×1
suspend ×1
try-catch ×1