如何在 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
包中的Future
、Callable
、Executor
类。
【讨论】:
如果有你想传递的变量怎么办?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 中调用具有单独线程的方法?的主要内容,如果未能解决你的问题,请参考以下文章