Java 爪哇8;在一个线程上利用睡眠时间,但在多个可调用线程上利用睡眠时间

Java 爪哇8;在一个线程上利用睡眠时间,但在多个可调用线程上利用睡眠时间,java,java-8,concurrency,Java,Java 8,Concurrency,在标准java8中,是否可以在单个线程上同时执行多个Callable? i、 e.当一个可呼叫设备睡眠时,开始处理另一个可呼叫设备 我当前的实验不起作用: ExecutorService executor = Executors.newSingleThreadExecutor(); List<Future> fs = new ArrayList<>(); for (int i = 0; i < 2; i++) { final

在标准java8中,是否可以在单个线程上同时执行多个Callable?
i、 e.当一个可呼叫设备睡眠时,开始处理另一个可呼叫设备

我当前的实验不起作用:

    ExecutorService executor = Executors.newSingleThreadExecutor();
    List<Future> fs = new ArrayList<>();
    for (int i = 0; i < 2; i++) {
        final int nr = i;
        fs.add(executor.submit(() -> {
            System.out.println("callable-" + nr + "-start");
            try { Thread.sleep(10_000); } catch (InterruptedException e) { }
            System.out.println("callable-" + nr + "-end");
            return nr;
        }));
    }
    try { executor.awaitTermination(5, TimeUnit.SECONDS); } catch (InterruptedException e) { }
我想要:

callable-0-start
callable-1-start
callable-0-end
callable-1-end
注:

  • 我有点期待一个答案:“不,这是不可能的。这不是线程的工作方式。一旦线程被分配给某些可执行代码,它就会一直运行到完成、异常或取消。在可调用/可运行之间不能有中途切换。
    thread.sleep
    只允许其他线程在CPU/内核上运行。”(明确的确认会让我安心)
  • 当然,这就是“玩具”的例子
  • 这是关于理解,而不是我遇到的具体问题

您试图做的是模拟旧java版本中不推荐使用的功能。那时可以停止、挂起或恢复
线程。但是可以从
线程的javadoc停止

此方法本质上是不安全的。使用thread.stop停止线程会导致它解锁所有已锁定的监视器(这是未检查的ThreadDeath异常向堆栈上传播的自然结果)。如果以前受这些监视器保护的任何对象处于不一致的状态,则损坏的对象将对其他线程可见,这可能会导致任意行为。停止的许多用法应替换为只修改某些变量以指示目标线程应停止运行的代码。目标线程uld定期检查此变量,如果该变量指示要停止运行,则按顺序从其运行方法返回。如果目标线程等待很长时间(例如,在条件变量上),则应使用中断方法中断等待

正如这篇文章所描述的,做你想做的事情的风险是至关重要的,因此这种行为已被弃用


我建议,与其试图从外部将正在运行的线程强制到某种停止位置,不如考虑一种线程池API,它允许您正确打包代码段,以便可以从线程中卸载它们的状态,然后再恢复。例如,创建
Ticket
,这将是一个元素一个线程总是在开始另一个任务之前完成的任务,
TicketChain
,它按顺序连接票据并存储状态。然后创建一个处理程序,逐个处理票据。以防当前无法完成票据(例如,因为并非所有数据都存在,或者无法获取某些锁)线程可以跳过它,直到稍后某个时间点,当所述条件可能为真时。

基于@TreffnonX的答案

实现所需标准输出结果的一种方法是使用CompletableFuture
(可调用代码必须显式拆分为单独的函数):


一个只有一个线程的池,你向它提交两个任务…你已经知道答案了,看起来你可能想看一看。我想,继续是你想要的
callable-0-start
callable-1-start
callable-0-end
callable-1-end
    ExecutorService executor = Executors.newSingleThreadExecutor();
    CompletableFuture<Integer>[] fs = new CompletableFuture[2];
    for(int i=0; i<2; i++) {
        final Integer ii = i;
        fs[i] = (CompletableFuture.completedFuture(ii)
                .thenApply((Integer x) -> { System.out.println("callable-" + x + "-start");return x; })
                .thenApplyAsync((Integer x) -> { try { Thread.sleep(1_000); } catch (InterruptedException e) {Thread.currentThread().interrupt();} return x; }, executor)
                .thenApply((Integer x) -> { System.out.println("callable-" + x + "-end");return x; }));
    }
    CompletableFuture.allOf(fs).join();
    try { executor.awaitTermination(5, TimeUnit.SECONDS); } catch (InterruptedException e) { }
callable-0-start
callable-1-start
callable-0-end
callable-1-end