The question is, is it possible to have an external thread or do they have to be internal to the class they run in. If so could someone show me how. (external thread)
问题:
回答1:
A thread, or, more precisely, a thread of execution is something, and the class Thread
is something closely related but different, and it seems that you are mixing up these two concepts.
You can think of a thread of execution as a machine that will execute operations sequentially. One way to define and run such a machine is to write a class MyClass
with a main()
method and call java MyClass
.
Another way is to create a new instance of the Thread
class and call its method start()
. This will create a new thread of execution which will run the code that is in the run()
method of the Thread
class, which does nothing by default. For this to be useful, you usually override the run
method, which is what I think you are calling a thread internal to the class...:
class MyThread extends Thread {
@Override public void run() {
// ... some code ...
}
}
// ...
final Thread t = new MyThread();
t.start();
In this example, after the run()
method of the class MyThread
returns, the thread of execution associated to that instance of MyThread
will terminate (just like when your single-threaded program returns from -- or reaches the end of -- your main()
method).
Another possibility is to pass the Thread
an instance of a Runnable
. Then you separate the 2 concepts: the thread of execution, which is represented by an instance of Thread
, will execute the code in the instance of Runnable
:
class MyRunnable implements Runnable {
@Override public void run {
// this code will get executed by a thread
}
}
// ...
final MyRunnable r = new MyRunnable();
final Thread t = new Thread(t);
t.start();
This maybe closer to what you call an external thread, although this nomenclature is highly unconventional.
So, you see that there are 2 different, but closely related, concepts here.
Now, in Java you have a way to create a thread of execution that will be waiting for you to give it some code to execute. After it is created, it goes to a pool, and sits there. You submit some code for it to run, and when it finishes, instead of terminating, the thread of execution keeps alive and goes back to that pool. Maybe this is what you are looking for.
To do it, you usually use an ExecutorService
. For example:
class MyMainClass {
private static final ExecutorService es = Executors.newFixedThreadPool(10);
public static void main(String... args) {
es.submit(new MyRunnable());
es.submit(new MyRunnable());
es.submit(new MyRunnable());
es.submit(new MyRunnable());
es.submit(new MyRunnable());
}
}
In this example, the pool contains 10 threads of execution. You can submit any amount of instances of Runnable
for it, and it will distribute them among the 10 threads. Each call to submit(...)
on the ExecutorService
returns an instance of Future
, which you can use to know if the thread of execution that was running your Runnable
did already finish, and if it finished successfully or due to an uncaught exception.
I suggest that you take a look at the javadocs for all the classes I mentioned here: Thread
, Runnable
, ExecutorService
, Executors
and Future
. There's a lot to learn from that documentation!
As a final note, remember that if you start playing with threads and ExecutorService
s, you will get all kinds of headache. You will have to think about situations in which the execution cannot proceed (deadlocks, livelocks), about operations that need to be atomic (ie, incrementing a variable from different threads), memory visibility (ie, if you change the value of a field without "taking care", it can happen that other threads will never notice the change to that field!). Also remember that the JVM won't die until every last non-daemon thread finishes; in other words, the example above will never terminate, even if all the submitted Runnable
s finish, because the threads of execution in the ExecutorService
are still alive!