在Executor服务中的ThreadPool中添加线程

时间:2013-03-05 17:56:52

标签: java multithreading threadpool executorservice

我正在开发一个多线程程序,我正在尝试确保每个线程都在运行30 minutes。假设我们有10 threads,则10中的每个帖子都应该为30 minutes运行。

以下是我的代码 -

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

3 个答案:

答案 0 :(得分: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); 
    }
}

答案 1 :(得分:0)

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

如果是这种情况:不要因为可以而创建1000个线程。相反,说出你真正想要实现的目标。

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

答案 2 :(得分:0)

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

决定线程开始时间的主线程。

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