简体   繁体   English

具有返回值的对象中的Java线程方法

[英]java threading method within object with return value

I am pretty new to using multithreading, but I want to invoke a method asynchronously (in a separate Thread ) rather than invoking it synchronously. 我对使用多线程非常陌生,但是我想异步地(在单独的Thread )调用一个方法,而不是同步地调用它。 The basic idea is that I'm creating a socket server with an object in memory, so for each client I will have to run something like object.getStuff() asynchronously. 基本思想是,我要创建一个内存中有对象的套接字服务器,因此对于每个客户端,我都必须异步运行诸如object.getStuff()类的东西。

The two constructs I found were: 我发现的两个构造是:

  1. having the class implement Runnable and threading this and 让类实现Runnable并this线程化
  2. declaring a runnable class within a method. 在方法中声明runnable类。

Additionally this method needs a return value- will it be necessary to use Executor and Callable to achieve this? 另外, this方法需要返回值-是否有必要使用ExecutorCallable来实现? Could someone point me in the right direction for implementing this? 有人能指出我正确的方向吗?

I have tried implement option 2, but this doesn't appear to be processing concurrently: 我已经尝试实现选项2,但这似乎不是同时处理的:

public class Test {
    private ExecutorService exec = Executors.newFixedThreadPool(10);

    public Thing getStuff(){

        class Getter implements Callable<Thing>{
            public Thing call(){
                //do collection stuff
                return Thing;
            }
        }

        Callable<Thing> callable = new Getter();
        Future<Thing> future = exec.submit(callable);
        return future.get();   
    }    
}

I am instantiating a single test object for the server and calling getStuff() for each client connection. 我正在为服务器实例化一个测试对象,并为每个客户端连接调用getStuff()。

Threading Tutorial 线程教程

The Java tutorial on concurrency has a good section on this. 关于并发的Java教程对此做了很好的介绍。 It's at https://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html . https://docs.oracle.com/javase/tutorial/essential/concurrency/runthread.html Essentially, you can either implement Runnable or Callable , or inherit from Thread . 本质上,您可以实现RunnableCallable ,也可以从Thread继承。

Subclassing Thread 子类化线程

You can write a class, including an anonymous inner class, that extends Thread . 您可以编写一个扩展Thread的类,包括一个匿名内部类。 Instantiate it, then invoke the start() method. 实例化它,然后调用start()方法。

public class MyThread extends Thread {
  public void run() {
    System.out.println("This is a thread");
  }
  public static void main(String[] args) {
    MyThread m = new MyThread();
    m.start();
  }
}

Implementing Runnable 实施可运行

You can write a class that implements Runnable , then wrap an instance in a Thread and invoke start() . 您可以编写实现Runnable的类,然后将实例包装在Thread并调用start() Very much like the previous. 非常像以前。

public class MyRunnable implements Runnable {
  public void run() {
    System.out.println("This is a thread");
  }
  public static void main(String[] args) {
    MyRunnable r = new MyRunnable();
    (new Thread(r)).start();
  }
}

Return Value 返回值

Runnable doesn't allow for return values. Runnable不允许返回值。 If you need that, you need to implement Callable instead. 如果需要,则需要实现Callable Callable looks a lot like Runnable , except you override the call() method instead of the run() method, and you need to give it to an ExecutorService . CallableRunnable看起来非常相似,除了您重写call()方法而不是run()方法,并且需要将其提供给ExecutorService

public class MyCallable implements Callable<Integer> {
  public Integer call() {
    System.out.println("A thread using Callable<Integer>");
    return 42;
  }
  public static void main(String[] args) {
    MyCallable c = new MyCallable();
    Future<Integer> f = Executors.newSingleThreadExecutor().submit(c));
    System.out.println("The thread returned: " +
      f.get());
  }
}

The two constructs I found were 1) having the class implement Runnable and threading 'this' and 2) declaring a runnable class within a method. 我发现的两个构造是:1)使类实现Runnable和线程化“ this”,以及2)在方法中声明一个可运行类。

Option (2) probably is better. 选项(2)可能更好。 Most programs would be improved if they had more classes, not fewer. 如果更多的课程,而不是更少的课程,大多数程序将得到改进。 Each named entity in a program—each package, class, method, whatever—should have just one responsibility. 程序中的每个命名实体(每个程序包,类,方法等等)都应该只承担一个责任。 In your option (1), you are asking the class to do two things. 在选项(1)中,您要求班级做件事。

For your option (2), you don't actually have to declare a whole class. 对于您的选择(2),您实际上不必声明整个类。 You can either use an anonymous inner class , or if you can go with Java8 all the way, you can use a lambda expression . 您可以使用匿名内部类 ,或者如果可以完全使用Java8,则可以使用lambda表达式 Google for either one to learn more. 谷歌为任何一个了解更多。

Additionally this method needs a return value. 另外,此方法需要一个返回值。

The classic way, is for the Runnable object to return the value through one of its own fields before the thread terminates. 经典方法是让Runnable对象在线程终止之前通过其自己的字段之一返回值。 Then the parent thread, can examine the object and get the return value afterward. 然后,父线程可以检查对象,然后获取返回值。

Will it be necessary to use Executor and Callable to achieve this? 是否需要使用Executor和Callable来实现这一目标?

Necessary? 必要? A lot of people think that ExecutorService is a Good Thing. 许多人认为ExecutorService是一件好事。

Sounds like you are creating a server that serves multiple clients. 听起来您正在创建一个服务于多个客户端的服务器。 Do these clients continually connect and disconnect? 这些客户端是否持续连接和断开连接? The advantage of using a thread pool (ie, ThreadPoolExecutor ) is that it saves your program from continually creating and destroying threads (eg, every time a client connects/disconnects). 使用线程池 (即ThreadPoolExecutor )的优点在于,它可以避免您的程序不断创建和销毁线程(例如,每次客户端连接/断开连接时)。 Creating and destroying threads is expensive. 创建和销毁线程非常昂贵。 If you have a lot of clients connecting and disconnecting, then using a thread pool could make a big difference in the performance of your server. 如果您有许多客户端进行连接和断开连接,则使用线程池可能会对服务器的性能产生很大的影响。

Creating and managing threads by yourself is generally bad approach. 自己创建和管理线程通常是不好的方法。 As you already pointed - use Executors utility class to create executor and submit Callable s to it. 正如您已经指出的那样-使用Executors实用程序类创建executor并将其提交Callable

public class RunWResult implements Runable{
    private volatile ResultType var;

    //the thread method
    public void run(){
        ...

        //generate a result and save it to var
        var = someResult();

        //notify waiting threads that a result has been generated
        synchronized(this){
            notify();
        }
    }

    public ResultType runWithResult(){
        //run the thread generating a result
        Thread t = new Thread(this);
        t.start();

        //wait for t to create a result
        try{
            wait();
        }catch(InterruptedException e){}

        //return the result
        return var;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM