是否可以从Java中的工作线程调用主线程?

时间:2012-02-01 17:38:34

标签: java multithreading worker-thread

我有一个名为action()的方法,它可以部署三个线程。每个部署的线程或工作线程都基于boolean类型为true的单个实例变量进入while循环,例如boolean doWork = true,每个线程都有一个while(doWork){}循环。

当线程完成作业时,会将doWork设置为false,从而阻止所有线程循环。然后我希望能够以某种方式让主线程回想起action()方法来重新部署线程来做另一个工作。 (如果我使用其中一个工作线程调用action()方法是否可以?)工作线程一旦调用action()方法就会终止并以某种方式死掉?

为简单起见,我将示例限制为两个线程

由于

class TestThreads{
    boolean doWork = true;

    void action(){
         ThreadOne t1 = new ThreadOne();
         ThreadTwo t2 = new ThreadTwo();
    }

    //innerclasses

    class ThreadOne implements Runnable{
          Thread trd1;
          public ThreadOne(){//constructor
              if(trd1 == null){
                   trd1 = new Thread(this);
                   trd1.start();
              }
          }
          @Override
          public void run(){
              while(doWork){
                   //random condition
                   //would set doWork = false;
                   //stop all other threads
              }
              action();//is the method in the main class
          }
    }
    class ThreadTwo implements Runnable{
          Thread trd2;
          public ThreadTwo(){//constroctor
              if(trd2 == null){
                   trd2 = new Thread(this);
                   trd2.start();
              }
          }
          @Override
          public void run(){
              while(doWork){
                   //random condition
                   //would set doWork = false;
                   //stop all other threads
              }
              action();//is the method in the main class
          }
    }

}

5 个答案:

答案 0 :(得分:4)

这个实现怎么样:

声明一个类成员doWork,一个用于当前活动线程和同步对象的计数器:

private volatile boolean doWork = true;
private AtomicInteger activeThreads;
private Object locker = new Object();

主要:

while(true) {
    // call action to start N threads
    activeThreads = new AtomicInteger(N);
    action(N);
    // barrier to wait for threads to finish
    synchronized(locker) {
       while(activeThreads.get() > 0) {
           locker.wait();
       }
    }
}

在线程正文中:

public void run() {
   while(doWork) {
      ...
      // if task finished set doWork to false
   }

   // signal main thread that I've finished
   synchronized(locker) {
      activeThreads.getAndDecrement();
      locker.notify();
   }
}

答案 1 :(得分:3)

骨架代码

// OP said 3 threads...
ExecutorService xs = Executors.newFixedThreadPool(3);

...

// repeat the following as many times as you want...
// this is the setup for his 3 threads - as Callables.

ArrayList<Callable<T>> my3Callables = new ArrayList<Callable<T>>();
my3Callables.add(callable1);
my3Callables.add(callable2);
my3Callables.add(callable3);

try {
   List<Future<T>> futures = xs.invokeAll(my3Callables );

   // below code may not be needed but is useful for catching any exceptions
   for (Future<T> future : futures) {
      T t = future.get();
      // do something with T if wanted
   }
}
catch (ExecutionException ee) {
  // do something
}
catch (CancellationException ce) {
  // do something
}
catch (InterruptedException ie) {
  // do something
}

答案 2 :(得分:2)

我会扩展我的评论(即使@babernathy将此添加到他的答案中)。

通常情况下,如果您有一个线程,您想要执行某项工作,并且您有一个主线程来管理您想要完成的工作项,ExecutorService提供了理想的框架。

在您的主对象中,您可以创建服务的实例(具有您想要的线程数),然后在生成一项工作时,将其提交给服务,然后服务将选择下一个可用的服务来自池的线程并执行它。

如果您依赖于知道特定工作是否已完成,则可以使用CountDownLatch之类的内容来跟踪线程何时完成其工作。我的观点是,这种活动有很多现有的框架,不需要再次经历痛苦......

答案 3 :(得分:1)

在没有任何代码的情况下为您提供准确的解决方案有点困难。这听起来像是在描述生产者/消费者模式,在这种模式中,您为一组工作线程提供了一些任务,当它们完成时,您会给它们更多。

这是一个web page,可以很好地描述要做什么。

另请查看允许您提交Runnables并让它们执行的ExecutorService

答案 4 :(得分:1)

一个简单的解决方案是让主线程处于休眠状态:

static boolean doWork = true; // better to use AtomicBoolean

void action() {

    // start workers, which eventually set doWork = false

    while (doWork) {    
        Thread.sleep(/**time in millis**/); // main thread waits for workers
    }

    // logic to run action() again, etc.

}

主线程启动工作人员,定期醒来检查他们是否已经终止。由于主线程是一个“仲裁者”,它可能不应该只是被其中一个孩子复活而死。

<强>参考