Reputation: 799
I'm making an animation. I'm generating a bunch of images and I want to add these to a gif encoder. As the process of adding might take quite some time, I want this to be done in a separate thread. My idea would be to do this:
public class MyThread implements Runnable {
private AnimatedGifEncoder encoder = new AnimatedGifEncoder();
public void run() {
encoder.start("MyFile.gif");
}
public void addFrame(BufferedImage img) {
encoder.add(img);
}
}
Then I would call the addFrame()
method from the main class every time a frame needs to be added. However, when I gave it a second thought, I concluded that this is not how it works.
Another idea is to create a new thread object for every time a frame is added:
public class MyMainClass {
while (generating) {
BufferedImage img = generateImg();
new Thread(() -> {
encoder.addFrame(img);
}).start();
}
}
However, to me this seems like a very heavy way to do this.
My question: what is a better way to achieve this? If there is not, is the idea of creating a new Thread
object really that heavy?
Upvotes: 0
Views: 79
Reputation: 27210
About your first idea
Your MyThread
class is not a thread. It's just a class with methods named run()
and addFrame(...)
. When your program executes the following, The run method will be called in the new thread:
MyThread myThread = new MyThread();
new Thread(myThread).start();
But, if your main thread later calls myThread.addFrame(...)
, that happens in the main thread. You can't write code that calls a method in another thread. Method calls happen in the thread that does the call. Always.
About your second idea
You're right. It's heavy-weight. Creating new threads is expensive. That's one reason why thread pools were invented. (See Peter Lawrey's answer)
The other reason thread pools were invented is to let your program manage the number of threads doing work at any given time. Nothing stops the main thread in your second example from creating a hundred new worker threads, or ten thousand, or... One after another.
With a thread pool, the threads are de-coupled from the work that they do. You can give the thread pool ten-thousand jobs to do, but it may only use ten threads to do them. Depends how the thread pool is configured.
The one in Peter Lawrey's example is configured to use just one worker thread.
Other methods of the java.util.concurrent.Executors
class will create differently configured thread pools for you, or you can configure something even more sophisticated by explicitly constructing and configuring a java.util.concurrent.ThreadPoolExecutor
instance.
Upvotes: 1
Reputation: 533880
You could use an ExecutorService
ExecutorService es = Executors.newSingleThreadExecutor();
es.submit(() -> encoder.start("MyFile.gif"));
es.submit(() -> encoder.addFrame(img));
Upvotes: 1