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

在Java中如何使用单独的线程调用方法?,java,multithreading,Java,Multithreading,假设我有一个方法doWork()。如何从单独的线程(而不是主线程)调用它。创建一个实现Runnable接口的类。将要运行的代码放在run()方法中-这是您必须编写的方法,以符合Runnable接口。在“主”线程中,创建一个新的thread类,向构造函数传递Runnable的实例,然后对其调用start()start告诉JVM神奇地创建一个新线程,然后在新线程中调用run方法 public class MyRunnable implements Runnable { private in

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

创建一个实现
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.util.concurrent
包中的
Future
Callable
Executor
类。

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

查看我在哪里记录了这个实用程序

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


在Java8中,只需一行代码就可以做到这一点

如果您的方法不采用任何参数,则可以使用方法引用:

new Thread(MyClass::doWork).start();
否则,可以在lambda表达式中调用该方法:

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

另一种更快的调用方法(如DialogBox和MessageBox以及为非线程安全的方法创建单独的线程)是使用Lamba表达式

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

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

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

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

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

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

CompletableFuture.supplyAsync(() -> 1);

在最近的相关问题上,碰巧有一些例子:我有一个类似的问题,请帮助我解决这个问题。你可能还想看看异步任务的反应式Java未来和可调用为你做这类事情。是的,他们做了。这里的想法是在异步包装器后面抽象接口。链接已断开(404)。如果有要传递的变量,该怎么办?
run()
方法不带任何参数,因此无法在那里传递变量。我建议你在构造函数中传递它-我会编辑我的答案来说明这一点。有没有一种在不同线程中调用1方法的简单方法?我知道
new Thread(){public void run(){myMethod();}}}.start()
way,这是最短的吗?@NoelM你能解释你的答案和MANN的答案之间的区别吗?MANN的答案使用了
Runnable
的匿名实现-mine是一个扩展
Runnable
的类。因为我已经这样做了,所以我有了自己的构造函数,它将状态传递给实例化的对象。这对我所做的工作非常有效。需要使用observer模式同时运行Web服务和更新进度条。@Ashish:请解释编辑的内容和原因?@AshishAggarwal:如果有人未经作者许可就这样做,我会觉得很奇怪!我们需要显式终止线程吗?不显式终止线程不存在造成内存泄漏的风险吗?或者线程在使用
run()
完成时终止了吗?在Java 8和更高版本中,我们可以用
()->myCustomMethod()
替换
new Runnable(){…}
详细的内容。很抱歉,让我们回到这里,但是
->
到底意味着什么?这是用于创建lambda表达式的语法。查看这些链接以获取更多信息:,以及@AaronCohn great stuff man!你知道Java中线程的替代方案吗?我来自Python世界,我们将使用
芹菜任务队列
来处理Java所拥有的异步东西,但也许您正在寻找类似的东西?
new Thread(() -> doWork(someParam)).start();
  new Thread(() -> {
                      "code here"
            }).start();
Completable.fromAction(this::dowork).subscribeOn(Schedulers.io().subscribe();
CompletableFuture.runAsync(() -> {...});
CompletableFuture.supplyAsync(() -> 1);