简体   繁体   English

将一个简单的java对象从一个线程传递到另一个线程的快速方法

[英]Fast way to pass a simple java object from one thread to another

I have a callback which receives an object. 我有一个回调接收一个对象。 I make a copy of this object, and I must pass it on to another thread for further processing. 我复制了这个对象,我必须将它传递给另一个线程进行进一步处理。 It's very important for the callback to return as fast as possible. 回调尽可能快地返回非常重要。 Ideally, the callback will write the copy to some sort of lock-free container. 理想情况下,回调会将副本写入某种无锁容器。

I only have the callback called from a single thread and one processing thread. 我只有从单个线程和一个处理线程调用的回调。

I only need to pass a bunch of doubles to the other thread, and I know the maximum number of doubles (around 40). 我只需要将一堆双打传递给另一个线程,我知道双打的最大数量(大约40)。

Any ideas? 有任何想法吗? I'm not very familiar with Java, so I don't know the usual ways to pass stuff between threads. 我对Java不是很熟悉,所以我不知道在线程之间传递东西的常用方法。

If this is just a one-off thing - you get the 40- or so doubles, and want to start a new thread processing that, then you can do it like this: 如果这只是一次性的事情 - 你得到40左右的双打,并且想要开始新的线程处理,那么你可以这样做:

public void callback(final double[] myDoubles)
{
  new Thread(){
   public void run() {
      // you can use myDoubles here. it will run on a separate thread.
   }}.start()   
};

If this is something that happens often, then you will need to look into thread pools and use a java.utils.concurrent.BlockingQueue . 如果这是经常发生的事情,那么您将需要查看线程池并使用java.utils.concurrent.BlockingQueue Despite the name, the queue will only block if it becomes full. 尽管名称如此,但队列只有在满员时才会阻止。

You can create an array of doubles the appropriate size which your callback method puts into the queue. 您可以创建一个双精度数组,其大小与回调方法放入队列的大小相同。 The put() operation is very quick and so your callback method will not be delayed for long. put()操作非常快,因此您的回调方法不会延迟很长时间。 (unless the queue is full.) (除非队列已满。)

Your other thread will use the take() method on the queue to get the object when an object is available. 当对象可用时,您的其他线程将使用队列上的take()方法获取对象。 The take() method blocks until an object is available - if you don't want that, but prefer to keep the thread running, doing other things, then use poll() instead. take()方法阻塞直到一个对象可用 - 如果你不想这样,但更喜欢保持线程运行,做其他事情,然后使用poll()。

One final thing to consider is - do you want just one worker thread handling the doubles from the callback, or do you want several? 最后要考虑的是 - 你是否只想要一个工作线程处理来自回调的双打,或者你想要几个? Having one thread makes sense when the work needs to be done one at a time - eg if you write the array to a file, there's usually no point having multiple threads doing this. 当一个工作需要一次完成时,有一个线程是有意义的 - 例如,如果将数组写入文件,通常没有多个线程执行此操作。 Buf if the work done on each array is independent, then it's a good candidate for having multiple worker threads. 如果在每个数组上完成的工作是独立的,那么它是拥有多个工作线程的一个很好的候选者。

On how to "pass stuff between threads", keep in mind that the most important part of a thread in Java is the target , an instance of a class that implements java.lang.Runnable . 关于如何“在线程之间传递东西”,请记住,Java中线程最重要的部分是目标 ,即实现java.lang.Runnable的类的实例。 If you construct a Thread object without passing in a Runnable instance, then the target is the Thread object itself (because java.lang.Thread implements java.lang.Runnable ). 如果构造一个Thread对象而不传入Runnable实例,那么目标就是Thread对象本身(因为java.lang.Thread实现了java.lang.Runnable )。 Otherwise, you are likely creating a custom class that implements Runnable , constructing an instance of this class, and passing it to a newly-constructed Thread instance. 否则,您可能正在创建一个实现Runnable的自定义类,构造此类的实例,并将其传递给新构造的Thread实例。 In this case, the instance of the custom class is the target. 在这种情况下,自定义类的实例是目标。

Ensuring that the thread, basically the Runnable object, has access to an object is equivalent to ensuring that the Runnable object has a reference to the object as an instance variable, making the object accessible to the run method that is being executed in the thread. 确保线程(基本上是Runnable对象)可以访问对象,这相当于确保Runnable对象具有对象作为实例变量的引用,使得对象可以在线程中执行的run方法中访问。

Here is an example of how to pass a copy of a double array to a newly-created thread: 以下是如何将double数组的副本传递给新创建的线程的示例:

class MyRunner implements Runnable
{
    double[] m_data;

    public MyRunner(double[] data)
    {
        this.m_data = data;
    }

    public void run()
    {
        // this code is executed in a thread. It can access `m_data`.
    }
}

public class Callback
{
    public void doCallback(double[] data)
    {
        double[] dataCopy = null;
        if (data != null) {
            dataCopy = new double[data.length];
            System.arraycopy(data, 0, dataCopy, 0, data.length);
        }
        MyRunner target = new MyRunner(dataCopy);
        Thread worker = new Thread(target);
        worker.start();
    }
}

Create an implementation of Runnable that is constructed with the array of doubles and then pass it into a thread pool executor . 创建一个使用双精度数组构造的Runnable实现,然后将其传递给线程池执行程序

Like so: 像这样:

public class MyDoublesProcessor implements Runnable {
    double[] doublesArray;
    public MyDoublesProcessor(double[] array) {
        doublesArray = array;
    }

    public void run() {
        //do stuff with array
    }
}

Executor exec = Executors.newFixedThreadPool(1);

void callback(double[] array) { //or whatever your callback is
    exec.execute(new MyDoublesProcessor(array));
}

Will you be creating a new Thread, or do you need to access another thread that already exists? 您是要创建新线程,还是需要访问已存在的另一个线程?

In case 1, you could just request a new Thread from a threadpool, pass it the information, tell it to run, then return. 在案例1中,您只需从线程池请求一个新线程,传递信息,告诉它运行,然后返回。

In case 2, you might need to create an intermediate thread that you can pass your data to, then it holds onto the data and attempts to call a synchronized function on (for instance) a data processing thread. 在案例2中,您可能需要创建一个可以将数据传递给的中间线程,然后它保留数据并尝试在(例如)数据处理线程上调用同步函数。 If you don't pass to an intermediate thread, you have no idea how long you might block on passing data to your other synchronized thread. 如果您没有传递给中间线程,则不知道在将数据传递到其他同步线程时可能会阻塞多长时间。

From the java essentials on threadpooling: 从线程池上的java要点:

http://java.sun.com/docs/books/tutorial/essential/concurrency/pools.html http://java.sun.com/docs/books/tutorial/essential/concurrency/pools.html

The newCachedThreadPool method creates an executor with an expandable thread pool. newCachedThreadPool方法使用可扩展线程池创建执行程序。 This executor is suitable for applications that launch many short-lived tasks. 此执行程序适用于启动许多短期任务的应用程序。

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

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