如何在 Java 中调用具有单独线程的方法?

Posted

技术标签:

【中文标题】如何在 Java 中调用具有单独线程的方法?【英文标题】:How to call a method with a separate thread in Java? 【发布时间】:2011-03-30 04:57:57 【问题描述】:

假设我有一个方法doWork()。如何从单独的线程(不是主线程)调用它。

【问题讨论】:

在最近的相关问题上碰巧有一些例子:killing an infinite loop in java ***.com/questions/36832094/…我有类似的问题请帮我解决这个问题 您可能还想看看 Reactive Java blog.danlew.net/2014/09/15/grokking-rxjava-part-1 for asynchronous tasks 【参考方案1】:
Thread t1 = new Thread(new Runnable() 
    @Override
    public void run() 
        // code goes here.
    
);  
t1.start();

new Thread(new Runnable() 
     @Override
     public void run() 
          // code goes here.
     
).start();

new Thread(() -> 
    // code goes here.
).start();

Executors.newSingleThreadExecutor().execute(new Runnable() 
    @Override
    public void run() 
        myCustomMethod();
    
);

Executors.newCachedThreadPool().execute(new Runnable() 
    @Override
    public void run() 
        myCustomMethod();
    
);

【讨论】:

这非常适合我正在做的事情。需要使用观察者模式同时运行 Web 服务和更新进度条。 @Ashish:请解释一下编辑了什么内容和原因? @AshishAggarwal:如果有人在未经作者许可的情况下这样做,我觉得很奇怪! 我们需要显式终止线程吗?通过不显式终止线程是否存在创建内存泄漏的风险?或者线程在使用run() 完成后是否终止? 在 Java 8 及更高版本中,我们可以用 () -> myCustomMethod() 替换 new Runnable() ... 冗长的东西【参考方案2】:

创建一个实现Runnable 接口的类。将您要运行的代码放在run() 方法中——这是您必须编写以符合Runnable 接口的方法。在您的“主”线程中,创建一个新的Thread 类,将Runnable 的实例传递给构造函数,然后在其上调用start()start 告诉 JVM 使用魔法创建一个新线程,然后在该新线程中调用您的 run 方法。

public class MyRunnable implements Runnable 

    private int var;

    public MyRunnable(int var) 
        this.var = var;
    

    public void run() 
        // code in the other thread, can reference "var" variable
    


public class MainThreadClass 
    public static void main(String args[]) 
        MyRunnable myRunnable = new MyRunnable(10);
        Thread t = new Thread(myRunnable)
        t.start();
        

查看Java's concurrency tutorial 以开始使用。

如果您的方法将被频繁调用,那么每次都创建一个新线程可能不值得,因为这是一项昂贵的操作。最好使用某种线程池。查看java.util.concurrent 包中的FutureCallableExecutor 类。

【讨论】:

如果有你想传递的变量怎么办? run() 方法没有参数,所以你不能在那里传递变量。我建议您在构造函数中传递它 - 我将编辑我的答案以显示这一点。 在不同的线程中调用 1 个方法是否有捷径?我知道new Thread() public void run() myMethod();.start(); 方式,是最短的吗? @NoelM 你能解释一下你的答案和 MANN 的答案之间的区别吗? MANN 的回答使用了Runnable 的匿名实现——我的是一个扩展Runnable 的类。因为我已经这样做了,所以我有自己的构造函数,可以将状态传递给实例化对象。【参考方案3】:

在 Java 8 中,您只需一行代码即可完成此操作。

如果你的方法不带任何参数,你可以使用方法引用:

new Thread(MyClass::doWork).start();

否则,您可以在 lambda 表达式中调用该方法:

new Thread(() -> doWork(someParam)).start();

【讨论】:

很抱歉把这个带回来,但 -> 到底是什么意思? 这是用于创建 lambda 表达式的语法。查看这些链接以获取更多信息:What does '->' do in Java? 和 The Java™ Tutorials - Lambda Expressions @AaronCohn 好东西!你知道Java中线程的任何替代品吗?我来自 Python 世界,我们会使用 Celery task queue 来处理异步内容 Java 有 higher level abstractions for dealing with Threads,但也许您正在寻找类似 @​​987654324@ 的东西?【参考方案4】:

如果您至少使用 Java 8,则可以使用类 CompletableFuture 中的方法 runAsync

CompletableFuture.runAsync(() -> ...);

如果您需要返回结果,请改用supplyAsync

CompletableFuture.supplyAsync(() -> 1);

【讨论】:

【参考方案5】:

另一个更快的调用方法(如对话框和消息框以及为非线程安全方法创建单独的线程)是使用 Lamba 表达式

  new Thread(() -> 
                      "code here"
            ).start();

【讨论】:

【参考方案6】:

要使用 RxJava 2.x 实现这一点,您可以使用:

Completable.fromAction(this::dowork).subscribeOn(Schedulers.io().subscribe();

subscribeOn() 方法指定在哪个调度程序上运行操作 - RxJava 有几个预定义的调度程序,包括 Schedulers.io(),它有一个用于 I/O 操作的线程池,以及Schedulers.computation(),它用于 CPU 密集型操作.

【讨论】:

【参考方案7】:

前段时间,我写了一个简单的实用程序类,它使用 JDK5 执行器服务并在后台执行特定进程。由于 doWork() 通常会有一个 void 返回值,因此您可能希望使用此实用程序类在后台执行它。

请参阅this article,我在其中记录了此实用程序。

【讨论】:

Future 和 Callable 为你做这种事情。 是的。这里的想法是抽象异步包装器背后的接口。 链接已损坏 (404)。 @palacsint 我更改了链接。现在它将起作用。对此感到抱歉

以上是关于如何在 Java 中调用具有单独线程的方法?的主要内容,如果未能解决你的问题,请参考以下文章

在单独的线程上调用我的方法都有哪些不同的方法?

如何在具有单独视图的控制器中使用加速度计?

如何将C / C ++库代码封装为可在具有多个实例的单独线程中运行?

Python:定时在单独的线程中调用的函数

如何在 C++ 中运行具有仅调用线程的函数的类的多个对象?

java笔试题整理