Preliminary creation of objects in a separate stream

Suppose I have a Java method:

public Ouput respond(Input input) { /* .. */ }

An object Outputhas many fields — some of these fields depend on the object Input, but the rest are predefined. I want to make a thread that calls respond()to return as quickly as possible.

To do this, I want to create another thread that pre-creates the object Output, sets some of the fields and puts them in the queue so that the thread executing respond()can select it from the queue, set the remaining fields and return it.

What is the best way to implement something like this? My prototype uses limited LinkedBlockingQueue, but are there any better ways to implement this idea?

My goal is to get the method as quickly as possible respond(), so other suggestions that fit this purpose are also welcome. :-)

+3
source share
6 answers

This is similar to the case where you could use a good Futureand Executors. See here for more details:

Here is a concrete example:

ExecutorService executor = Executors.newSingleThreadExecutor();

final Input input = ...
Future<Output> future = executor.submit(new Callable<Output>() {
  public Output call() {
    return respond(input);
  }
});

// do some work

Output output = future.get();  // this blocks until it done

, , Output , , Output, . :

public class Output {
   private String fieldA; // immediate field
   private Future<String> fieldB; // delayed field

   public void setFieldA(String fieldA) { this.fieldA = fieldA; }
   public String getFieldA() { return fieldA; } 
   public void setFieldB(Future<String> fieldB) { this.fieldB = fieldB; }
   public Future<String> getFieldB() { return fieldB; }
}

:

public Output respond(final Input input) {
   Output output = new Output();
   String fieldA = ...
   output.setFieldA(fieldA);

   Future<String> fieldBFuture = executor.submit(new Callable<String>() {
     public String call() {
       String fieldB = ...
       return fieldB;
     }
   }

   output.setFieldB(fieldBFuture);
}

Output:

Input input = ...
Output output = respond(input);

String fieldA = output.getFieldA();
// do some work
String fieldB = output.getFieldB().get();
+3

, , reply(), Output, . , , , , Java VM.

, , , ().

, . , .

+2

, Output, , , .

+2

- factory, Output, , , ? , - ( , , , , , , , , ..):

public class OutputFactory {

    private List<Output> outputPool = new LinkedList<Output>();

    public OutputFactory() {
        this.populatePool();
    }

    private void populatePool() {
        // spawn a new thread here, if you wish, to optimize time-to-return
        for (int i = 0; i < 100; i++) {
            outputPool.add(new Output());
        }
    }

    public Output getNewOutput() {
        Output newOutput = outputPool.remove(0);
        if (outputPool.size() < 10) {
            populatePool();
        }
        return newOutput;
    }

}
+1

, , . , , .

. , respond() . ( , , .)

If the template does not work, but you can reuse the output instances, which is probably even better, since no new memory needs to be allocated at all, and the predefined fields do not even need to be copied; they will already be installed.

Any of these strategies will allow you to speed up the method respond()without the overhead of a separate thread.

+1
source

If the rest of the fields are really “predefined”, why not make them static in the Output class?

0
source

Source: https://habr.com/ru/post/1726918/


All Articles