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

11,013

Solution 1

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:

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. 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. (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. 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.

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 - e.g. 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.

Solution 2

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. 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). 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. 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.

Here is an example of how to pass a copy of a double array to a newly-created thread:

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();
    }
}

Solution 3

Create an implementation of Runnable that is constructed with the array of doubles and then pass it into a thread pool executor.

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));
}
Share:
11,013
Meh
Author by

Meh

Updated on June 05, 2022

Comments

  • Meh
    Meh almost 2 years

    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).

    Any ideas? I'm not very familiar with Java, so I don't know the usual ways to pass stuff between threads.

  • Meh
    Meh almost 14 years
    For case 2, what if the callback is called again before the intermediate thread manages to pass the object to the third thread? How fast is getting a thread from a threadpool? Does it lock?
  • Zak
    Zak almost 14 years
    In case 2, you basically still do case 1 (create a new thread, managed by a thread manager) , but then let that thread wait on your processing thread. Answer edited to reflect threadpool information.
  • mdma
    mdma almost 14 years
    I wouldn't hand-code this stuff - it's much safer to use the concurrency utils.
  • Tim Bender
    Tim Bender almost 14 years
    Not all BlockingQueue implementations are bounded. Put only blocks for bounded implementations. Also, put the code block in an SO code block format.
  • mdma
    mdma almost 14 years
    I think you're splitting hairs here for a simple intro to passing values between threads. A LinkedBlockingQueue can be optionally "unbounded" by setting the bound size to Integer.MAX_VALUE, but all queues run in a finite amount of space, and are in practice bounded by the amount of memory available. A bounded queue offers more useful semantics than an "unbounded" one, especially in the face of other concurrency bugs: if the worker thread is overworked or deadlocked, an unbounded queue will simply grow and grow. A bounded queue fails predictably, clearly indicating worker thread problems.
  • mdma
    mdma almost 14 years
    An notice I said that "the queue only blocks when it becomes full". An unbounded queue is never full and thus never blocks.