2013-03-05 65 views
4

我正在开发一个多线程程序,其中我试图确保每个线程都运行30 minutes。假设我们有10 threads,那么10中的每个线程都应该运行30 minutes在执行器服务中的ThreadPool中添加线程

下面是我的代码 -

class ThreadTask implements Runnable { 
    private final long endTime; 

    public ThreadTask(long endTime) { 
     this.endTime = endTime; 
    } 

    @Override 
    public void run() { 

     while (System.currentTimeMillis() <= endTime) { 

      // do something meaningful 

     } 
    } 
} 

public class TestPool { 

    public static void main(String[] args) { 

     // create thread pool with given size 
     ExecutorService service = Executors.newFixedThreadPool(1000); 

     long startTime = System.currentTimeMillis(); 
     long endTime = startTime + (30 * 60 * 1000); 

     for (int i = 0; i < threads; i++) { 
      service.submit(new ThreadTask(endTime)); 
     } 

     // wait for termination   
     service.shutdown(); 
     service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); 
    } 
} 

现在我的问题是 -

请问上面的代码保证每个线程开始在同一时间和运行30 minutes?我不确定将线程放入线程池需要多少时间。但看起来有些线程可能会稍微晚一些,并且它们不会精确运行30 minutes,可能会少于30分钟。

我要寻找每个线程应该开始在同一时间,他们应该 整整30 minutes

+0

不,他们不会在同一时间开始,不,他们不会正好30分钟,这取决于“有意义的事”需要多长时间运行。 – 2013-03-05 17:59:59

回答

1

简短的回答运行:没有,所有的线程将不完全在同一时间启动(取决于你的容忍度,它可能是'相当'可以忽略不计的)。取决于有意义的事情,每个线程运行30分钟的可能性非常小(再次,在这里,您的时间粒度可能会导致此断言错误)。

信息

  • 为确保最大限度地提高你的机会,所有的线程开始互相尽可能靠近,先创建线程,然后将其提交给执行者。在Java中与其他语言一样创建线程是一项昂贵的操作。
  • 为了让线程正好运行30分钟,我建议每个线程计算自己的终止时间,因为当前传递给构造函数的参数可能已经影响了您的精度(由于线程创建时间)。
  • 通常不推荐使用它(除非在怪物机器或微积分网格上运行java)创建一个拥有1000个线程的线程池。请记住,如果物理机器不具有与线程一样多的内核,则每次JVM决定运行哪个线程时都会发生上下文切换。

编辑

public class TestPool { 

    public static void main(String[] args) { 

     // create thread pool with given size 
     ExecutorService service = Executors.newFixedThreadPool(10); 

     long startTime = System.currentTimeMillis(); 
     long endTime = startTime + (30 * 60 * 1000); 

     ThreadTask[] threadTasks = new ThreadTask[threads]; 
     for (int i = 0; i < threads; i++) { 
      threadTasks[i] = new ThreadTask(endTime); 
     } 

     for (ThreadTask tt : threadTasks) { 
      service.submit(tt); 
     } 

     // wait for termination   
     service.shutdown(); 
     service.awaitTermination(Long.MAX_VALUE, TimeUnit.DAYS); 
    } 
} 
+0

感谢'aymeric'的建议。我主要关心你的第一点。我怎样才能做到这一点?你能用我的代码提供一个例子吗?通过这一点,我将能够更好地理解。谢谢您的帮助。 – AKIWEB 2013-03-05 21:21:15

+0

请参阅我的编辑... – aymeric 2013-03-06 10:01:07

0

乍一看,这看起来像一个有点不切实际多线程锻炼; Tibial项目。但你说我正在研究一个多线程程序,这表明它有一个真实世界的应用程序背景。

如果是这样的话:不要仅仅因为可以创建1000个线程。相反,说出你实际想要达到的目标。

关于您的要求:几乎在同一时间以最小的延迟启动所有线程,您可以prestartAllCoreThreadsThreadPoolExecutor。提交在其运行方法中有// do something meaningful的Runnables。要将运行时间限制为30分钟,可以安排一个TimerTask,在30分钟后用shutdownNow关闭ThreadPoolExecutor。在创建ThreadPoolExecutor时,可以使用固定大小的BlockingQueue,大小按照所需线程数的顺序,以避免提交太多作业。

0

考虑使用倒计数锁存器来实现最大并行性。基本上,你可以创建总数为1的singleton/static countdownLatch,并让多个线程等待相同的倒计时。请检查下面我做了什么

决定线程启动时间的主线程。

package mylab.threads; 

import java.util.TimerTask; 
import java.util.concurrent.CountDownLatch; 
import java.util.concurrent.ExecutorService; 
import java.util.concurrent.Executors; 

public class MainThread extends TimerTask { 

    private static CountDownLatch countDown = new CountDownLatch(1); 

    private ExecutorService es = Executors.newCachedThreadPool(); 

    @Override 
    public void run() { 

    try { 


     Thread1 thread1 = new Thread1(); 
     thread1.setDoneSignal(countDown); 
     es.submit(thread1); 

     Thread2 thread2 = new Thread2(); 
     thread2.setDoneSignal(countDown); 
     es.submit(thread2); 

     System.out.println("waiting main.. "); 
     synchronized(this) { 
     this.wait(2000); 
     } 
     System.out.println("kick off threads.."); 
     countDown.countDown(); 

    } catch (InterruptedException e) { 
     e.printStackTrace(); 
    } 

    } 

} 

定义要运行并行

package mylab.threads; 

import java.util.Date; 
import java.util.TimerTask; 
import java.util.concurrent.CountDownLatch; 

public class Thread1 extends TimerTask{ 

    private CountDownLatch doneSignal = null; 

    /** 
    * @return the doneSignal 
    */ 
    public CountDownLatch getDoneSignal() { 
     return doneSignal; 
    } 

    /** 
    * @param doneSignal the doneSignal to set 
    */ 
    public void setDoneSignal(CountDownLatch doneSignal) { 
     this.doneSignal = doneSignal; 
    } 

    @Override 
    public void run() { 

    try { 
     this.doneSignal.await(); 
     System.out.println("get going thread 1 -"+new Date().getTime()); 
     synchronized(this) { 
     this.wait(3000); 
     } 
     System.out.println("Exiting thread 1 - "+new Date().getTime()); 
    } catch (InterruptedException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    } 

} 


package mylab.threads; 

import java.util.Date; 
import java.util.TimerTask; 
import java.util.concurrent.CountDownLatch; 

public class Thread2 extends TimerTask{ 

    private CountDownLatch doneSignal = null; 

    /** 
    * @return the doneSignal 
    */ 
    public CountDownLatch getDoneSignal() { 
     return doneSignal; 
    } 

    /** 
    * @param doneSignal the doneSignal to set 
    */ 
    public void setDoneSignal(CountDownLatch doneSignal) { 
     this.doneSignal = doneSignal; 
    } 

    @Override 
    public void run() { 

    try { 
     this.doneSignal.await(); 
     System.out.println("get going thread 2 -"+new Date().getTime()); 
     synchronized(this) { 
     this.wait(3000); 
     } 
     System.out.println("Exiting thread 2 - "+new Date().getTime()); 
    } catch (InterruptedException e) { 
     // TODO Auto-generated catch block 
     e.printStackTrace(); 
    } 
    } 
} 

最后运行的主线程的线程。

package mylab.threads; 

public class ThreadTest { 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 

    MainThread mt = new MainThread(); 
    mt.run(); 

    } 

} 

这里是输出

waiting main.. 
kick off threads.. 
get going thread 1 -1387513662107 
get going thread 2 -1387513662107 
Exiting thread 1 - 1387513665108 
Exiting thread 2 - 1387513665108