我正在编写一个使用某些线程的Java应用程序。主要方法如下:
WorkerThread[] thread = new WorkerThread();
for (int i = 0 ; i<10 ; i++) {
thread = new WorkerThread();
thread.doStuff();
}
我的WorkerThread看起来像这样:
class WorkerThread {
public void run() {
...
}
public void doStuff() {
...
}
}
问题是,显而易见,我从run方法调用doStuff,它与其他线程同时执行,但如果我直接从main调用doStuff,则不会执行。
好的,现在的问题是:有没有办法同时执行doStuff方法,而不是从run方法调用它,而是从main中调用它?
答案 0 :(得分:2)
您无法直接调用Thread对象上的方法。使用Thread获得并发的唯一方法是调用其start()方法,该方法又在单独的执行线程上调用run()。直接从main()调用任何其他方法就像在常规非Thread对象上调用方法一样;没有并发,没有什么特别的事情发生,方法立即执行。
听起来你正试图在主线程和工作线程之间进行通信。每个线程的run()方法负责在该线程上执行代码。如果您可以使用该run()方法进行通信,那么您可以控制该线程上发生的事情。
一种方法是在构造Thread时传入一个变量。保存run()方法可以检查的值以确定要执行的操作。例如,下面我们有一个枚举,里面有三个可能的动作。 run()方法查看枚举,并根据传递给WorkerThread()构造函数的值决定要执行的操作。
class WorkerThread {
public enum Action { DO_STUFF, MAKE_WIDGETS, FROB_BARS }
private Action action;
public WorkerThread(Action action) {
this.action = action;
}
public void run (){
switch (action) {
case DO_STUFF: doStuff(); break;
case MAKE_WIDGETS: makeWidgets(); break;
case FROB_BARS: frobBars(); break;
}
}
public void doStuff() { ... }
public void makeWidgets() { ... }
public void frobBars() { ... }
}
现在我们的main()方法看起来像这样。您创建传入要执行的操作的WorkerThreads,然后调用start()。
WorkerThread[] threads = new WorkerThread[10];
for (int i = 0; i < threads.length; ++i) {
threads[i] = new WorkerThread(WorkerThread.Action.DO_STUFF);
threads[i].start();
}
你可以用无数种方式做同样的事情。您可以使用不同的run()方法,而不是拥有一个WorkerThread类,然后从main()实例化相应的子类。
class DoStuffWorkerThread extends Thread { ... }
class MakeWidgetsWorkerThread extends Thread { ... }
class FrobBarsWorkerThread extends Thread { ... }
如果愿意,您甚至可以在main()内创建匿名Thread类。然后逻辑可以是main()想要的任何东西。
Thread[] threads = new Thread[10];
for (int i = 0; i < threads.length; ++i) {
threads[i] = new Thread() {
public void run() {
doStuff();
}
};
threads[i].start();
}
答案 1 :(得分:0)
当您使用thread.doStuff();
时,您没有使用线程,因此要使用线程,您必须调用thread.start()
方法,该方法将在内部内部调用run()
方法。
答案 2 :(得分:0)
Thread[] threads = new Thread()[10];
for (int i = 0 ; i<10 ; i++) {
if ( i<5) {
threads[i] = new Thread(new WorkerA());
} else {
threads[i] = new Thread(new WorkerB());
}
threads[i].start();
}
首先,您正在创建一个数组,但不要正确使用它。您不能将对象分配给数组?
然后你必须调用start()
方法在后台执行线程并调用他的run方法。
你的工人应该是这样的:
class WorkerA implements Runnable {
public void run (){
...
// put here your code from doStuff in one Version
...
}
}
class WorkerB implements Runnable {
public void run (){
...
// put here your code from doStuff in an other Version
...
}
}
现在,您可以在任何地方调用它,而不是在循环中调用thread[i].start()
。
答案 3 :(得分:0)
您可以使用Runnable
。
// Dictate what work needs to be done
Runnable work = new Work(); // or new OtherWork();
Thread thread = new Thread(work);
thread.start();
class Work implements Runnable {
public void run(){
System.out.println("do stuff");
}
}
class OtherWork implements Runnable {
public void run() {
System.out.println(" do other stuff");
}
}
修改强>:
建议使用线程池而不是为每个任务创建(和丢弃)线程。这是因为在创建/丢弃线程时会有一些开销,并且还可以更容易地管理应该完成任务的并发性等。
无论如何,你可以使用Thread
类自己创建你的线程池,但这是很多工作而且很难做到正确。相反,最好使用JDK中提供的现成解决方案。您可以按如下方式使用它:
ExecutorService threadPool = Executors.newFixedThreadPool(4);
threadPool.execute(new Work());
threadPool.execute(new OtherWork());
// After submitting all your task (or when your application wants to terminate)
// You should call shutdown() on the thread pool so that the JVM can exit
threadPool.shutdown();