Java-重用具有相同运行但不同参数的线程
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/13106585/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java- reusing a thread with the same run but different parameters
提问by user1777900
I still have some trouble wrapping my head around threads, and I'm trying to do this in the simplest way possible. I know that threads all have to have a run method they inherited from the Runnable class, but they can have additional methods as well, correct?
我仍然在围绕线程缠绕我的头时遇到一些麻烦,我正在尝试以最简单的方式做到这一点。我知道线程都必须有一个从 Runnable 类继承的 run 方法,但它们也可以有其他方法,对吗?
The reason being, I have a thread with some private variables and a run method. It calls it's run function, and once it's done, I want to reuse the thread with the exact same run method. It does exactly the same thing, just with different variables. So can I add something like a setArray method (the thread contains a private byte array) so I can just simply call run again with this new array, or is that not allowed. I guess to put it simply, it'd be something like
原因是,我有一个带有一些私有变量和一个 run 方法的线程。它调用它的 run 函数,一旦它完成,我想用完全相同的 run 方法重用线程。它做的完全一样,只是变量不同。所以我可以添加类似 setArray 方法的东西(线程包含一个私有字节数组),这样我就可以简单地用这个新数组再次调用 run ,或者这是不允许的。我想简单地说,它会是这样的
Thread thread = new MyThread();
thread.start();
// Check if the thread has finished in a non-blocking way
if (thread.isAlive() == false) {
thread.setArray(newArray)
thread.start();
}
Basically I only have a fixed number of threads and when the first thread is done running, I want to change the parameters a bit and have it run again. I don't wan them to die, which seems to be what join does.
基本上我只有固定数量的线程,当第一个线程完成运行时,我想稍微更改参数并让它再次运行。我不希望他们死,这似乎是 join 所做的。
For the specific problem, I have say 4 threads, that each are give a set size block of a larger byte array. Each thread compresses that array with a Deflater and passes their result to a manager object that handles the synchronization. Once the first thread (as in the thread that got the first part of the array, not the first to finish) is done, it moves on to the next block not assigned to a thread.
对于特定问题,我已经说过 4 个线程,每个线程都给出了一个较大字节数组的固定大小块。每个线程使用 Deflater 压缩该数组,并将其结果传递给处理同步的管理器对象。一旦第一个线程(如在获得数组的第一部分的线程中,而不是第一个完成的线程)完成,它就会移动到下一个未分配给线程的块。
I know thread pools are an option, but it seems a bit overkill plus I really don't understand them (I'm still having trouble with just normal threads).
我知道线程池是一种选择,但它似乎有点矫枉过正,而且我真的不理解它们(我仍然无法使用普通线程)。
回答by Stephen C
First, it is best to use the standard Thread
class (don't subclass it!) and put your application code into a class that implements Runnable
. This makes it much easier to separate your application logic from the problem of managing the threads.
首先,最好使用标准Thread
类(不要子类化它!)并将您的应用程序代码放入一个实现Runnable
. 这使得将应用程序逻辑与管理线程的问题分开变得更加容易。
Second you have to understand that a Thread object calls the run
method just once. After the run
method has returned (or terminated with an exception), the Thread object is dead, and cannot be brought back to life.
其次,您必须了解 Thread 对象只调用run
一次该方法。在之后run
方法返回(或异常终止),Thread对象是死的,而不能起死回生。
So if you want to "reuse" Thread
instances, you have to arrange that the run
method is a loop that (somehow) waits for the next thing to be done. And before you know it you are implementinga thread pool.
因此,如果您想“重用”Thread
实例,则必须将该run
方法安排为一个循环,(以某种方式)等待下一件事情完成。在不知不觉中,您正在实现一个线程池。
There is another (more "modern") alternative to a thread pool. Create an ExecutorService
instance, and use the submit()
method to submit the Runnable
instances for execution. The interface javadoc has a good usage example, using an executor service instance with a private thread pool. If you wanted to, you couldreuse the Runnable
instances, but generally it is simpler (and safer) to create new ones each time.
线程池还有另一种(更“现代”的)替代方案。创建一个ExecutorService
实例,并使用该submit()
方法提交Runnable
实例以供执行。接口 javadoc 有一个很好的用法示例,使用带有私有线程池的执行器服务实例。如果您愿意,可以重用Runnable
实例,但通常每次创建新实例更简单(也更安全)。
回答by slipperyseal
Make a separate class for your code that implements Runnable. You will need to make new Thread objects each time, but construct these with your single Runnable object. The run method will be reused by each Thread.
为实现 Runnable 的代码创建一个单独的类。您每次都需要创建新的 Thread 对象,但使用单个 Runnable 对象构建这些对象。run 方法将被每个线程重用。
回答by Neil Coffey
A thread always starts exactly once, runs exactly once and then dies exactly once. So you can't call start() on the thread multiple times in the way that you suggest.
一个线程总是只启动一次,运行一次,然后只死一次。所以你不能按照你建议的方式在线程上多次调用 start() 。
So, one way or another, you have to either:
因此,以一种或另一种方式,您必须:
- Have a single thread that, one way or another within its run() method, executes each of your method calls with the different sets of parameters.
- Start a new thread for each "run" (method call to the Thing That You Actually Want To Do).
- 有一个线程,在其 run() 方法中以一种或另一种方式使用不同的参数集执行每个方法调用。
- 为每次“运行”启动一个新线程(对您实际想要做的事情的方法调用)。
Which implementation is more appropriate depends a little on your exact application. But in general, it is helpful to think of a thread as being a sub-task that runs parallelto other subtasks. So in general:
哪种实现更合适取决于您的具体应用。但总的来说,将线程视为与其他子任务并行运行的子任务会很有帮助。所以一般来说:
- if you have a series of independent "runs" of something which you have no reason to run in parallel to one another, arrange for these runs to be executed one after the other inside a single Thread.run() method;
- if you have a series of tasks that may as well run parallel to one another, put each in a separate Thread.
- 如果您有一系列独立的“运行”,而您没有理由彼此并行运行,请安排这些运行在单个 Thread.run() 方法中一个接一个地执行;
- 如果您有一系列任务也可以彼此并行运行,请将每个任务放在一个单独的线程中。
A thread pool is generally used for cases where at any given moment you can have some arbitrary task to execute, and such tasks can run in parallel. For example, on a typical server. Think of a web server receiving requests for pages from different clients at arbitrary points in time: each request can come at some arbitrary point in time and a request for a page from one client is completely independent from a request from another client. In principle, you don't care which requests run in parallel to which, other than that your machine has resource constraints such as the number of CPUs. For this type of case, where you effectively want to "run arbitrary tasks in arbitrary threads, up to a limit of X tasks running in parallel", you would generally use a thread pool.
线程池通常用于在任何给定时刻您可以执行一些任意任务的情况,并且这些任务可以并行运行。例如,在典型的服务器上。想象一下 Web 服务器在任意时间点接收来自不同客户端的页面请求:每个请求可以在任意时间点到来,并且来自一个客户端的页面请求完全独立于来自另一个客户端的请求。原则上,您并不关心哪些请求与哪些请求并行运行,除了您的机器具有资源限制(例如 CPU 数量)之外。对于这种类型的情况,您实际上希望“在任意线程中运行任意任务,最多可并行运行 X 个任务”,您通常会使用线程池。
回答by Jay Taggart
Threads are basically just objects with state and a method to run. Here's an example thread:
线程基本上只是具有状态和要运行的方法的对象。这是一个示例线程:
public class ThreadWithState implements Runnable {
private Object state;
public ThreadWithState(Object state) {
this.state = state;
}
public void run() {
// Do something with state
}
}
Threads are generally executed in parallel, otherwise the whole point of multi-threading is lost. Therefore, we try to use a pool of threads to execute, as demonstrated in the following Driver class:
线程一般是并行执行的,否则多线程的全部意义都没有了。因此,我们尝试使用线程池来执行,如下面的 Driver 类所示:
public class Driver {
public static void main(String[] args) {
ThreadWithState thread = new ThreadWithState(null);
ThreadWithState thread2 = new ThreadWithState(new Object());
ThreadWithState thread3 = new ThreadWithState(new Object());
ThreadWithState thread4 = new ThreadWithState(new Object());
ExecutorService service = Executors.newFixedThreadPool(4);
service.submit(thread);
service.submit(thread2);
service.submit(thread3);
service.submit(thread4);
service.shutdown();
}
}