创建2个线程,每个线程运行不同的任务

时间:2020-07-20 05:30:20

标签: java multithreading

我想在我的应用程序中创建两个线程,它们将运行两个方法。我使用的是构建器设计模式,在构建方法中,我有类似这样的内容,请求是传递的对象:

Rules rule;
        Request build() {
            Request request = new Request(this);
        //I want one threat to call this method
        Boolean isExceeding = this.rule.volumeExceeding(request);

        //Another thread to call this method
        Boolean isRepeating = this.rule.volumeRepeating(request);
        
        //Some sort of timer that will wait until both values are received,
        //If one value takes too long to be received kill the thread and continue with
        //whatever value was received.

        ..Logic based on 2 booleans..
        return request;
    }
        
    

这是这个类的样子:

public class Rules {

    public Boolean volumeExceeding(Request request) {

        ...some...logic...
        return true/false;
    }


    public Boolean volumeRepeating(Request request) {
       
        ...some...logic...
        return true/false;
    }
}

我已在代码中注释了我想发生的事情。基本上,我想创建两个线程来运行各自的方法。它会等到两者都完成后,但是,如果一个过程花费的时间太长(例如:超过10ms),则返回已完成的值。我该如何创建?我试图理解多线程教程,但是这些示例是如此的通用,以至于很难理解它们所做的事情并将其应用于更复杂的事情。

2 个答案:

答案 0 :(得分:2)

一种方法是使用CompletableFuture s:

import java.util.concurrent.CompletableFuture;

class Main {
    
    private static final long timeout = 1_000; // 1 second

    
    static Boolean volumeExceeding(Object request) {
        System.out.println(Thread.currentThread().getName());
        final long startpoint = System.currentTimeMillis();
        
        // do stuff with request but we do dummy stuff
        for (int i = 0; i < 1_000_000; i++) {
            if (System.currentTimeMillis() - startpoint > timeout) {
                return false;
            }
            Math.log(Math.sqrt(i));
        }
        return true;
    }
    
    
    static Boolean volumeRepeating(Object request) {
        System.out.println(Thread.currentThread().getName());
        final long startpoint = System.currentTimeMillis();
        
        // do stuff with request but we do dummy stuff
        for (int i = 0; i < 1_000_000_000; i++) {
            if (System.currentTimeMillis() - startpoint > timeout) {
                return false;
            }
            Math.log(Math.sqrt(i));
        }
        return true;
    }
    

    public static void main(String[] args) {
        final Object request = new Object();
        
        CompletableFuture<Boolean> isExceedingFuture = CompletableFuture.supplyAsync(
                () -> Main.volumeExceeding(request));
        CompletableFuture<Boolean> isRepeatingFuture = CompletableFuture.supplyAsync(
                () -> Main.volumeRepeating(request));
        
        Boolean isExceeding = isExceedingFuture.join();
        Boolean isRepeating = isRepeatingFuture.join();
        
        System.out.println(isExceeding);
        System.out.println(isRepeating);
    }
}

请注意,一项任务要比另一项花费更长的时间。

发生了什么事?您通过使用CompletableFuture执行将这些任务提供给公共池。两项任务均由两个不同的线程执行。您所要求的是,任务花费的时间太长就会停止。因此,您可以简单地记住任务开始的时间,并定期检查是否超时。 重要:进行此检查,以确保在数据保持一致状态时任务将返回。另外请注意,您当然可以进行多次检查。

关于CompletableFutureGuide To CompletableFuture

这是一个不错的指南

答案 1 :(得分:0)

如果我正确理解了您的问题,那么您应该使用票务系统(也称为提供者-消费者模式或生产者-消费者模式)来执行此操作,以便您的线程被重用(这是一个如果这些操作是时间紧迫的,则可以显着提高性能。

总体思路应该是:

应用初始化

  • 初始化2个或更多“消费者”线程,这些线程可以处理票证(也称为作业)。

运行时

  • 向消费者线程票证(或作业)供料,只要您愿意,便可以等待(大约)。但是,根据JVM的不同,等待时间很可能不是精确的n毫秒,因为对于超时的等待时间,调度程序通常更“宽松”。例如Thread.sleep()几乎总是相差一毫秒(据我所知,总是迟到,永远不会早到)。
  • 如果线程在给定的等待时间之后没有返回,则必须忽略此结果(根据您的逻辑),并且必须通知票证(因此线程)中止该票证。重要的是,不要中断线程,因为这可能导致异常或阻止锁被解锁。

请记住,从外部停止或停止线程总是存在锁问题,因此,我建议您的作业会定期访问可能的退出点,因此,如果您不再关心结果,则可以安全地终止它们。< / p>

相关问题