在main()函数中有100个线程,我希望等这些线程全部执行完毕后再执行一条语句,请问应该如何做?不能让这100线程全部join()吧?
public static void main(String[] args){
    for(int i = 0; i < 100; i++){
        new MyThread().start;
    }    /*这里应该如何处理?*/
    System.out.println("线程全部执行完毕"); 
}

解决方案 »

  1.   

    呵呵,写的标志类classc threadFlag(){private static  int count=0;public static addOne(){count++};
    public static clear(){count=0;} 
    }线程执行完时候执行下threadFlag.addOne();main里判断:
    if(threadFlag.count=100){ //打印}else{ wait();//等待}
      

  2.   

    通过监控Thread的 getState来监控 线程的状态
      

  3.   

    不过好象它是针对单个线程的对吧?
    是不是还要getThreadGroup() 来获得线程组?isAlive()可以对线程组操作么?
      

  4.   

    classc threadFlag(){private static  int count=0;public static addOne(){count++};
    public static minusOne(){count--};
    public static clear(){count=0;} 
    }线程构造函数里执行下threadFlag.addOne();线程执行完时候执行下threadFlag.minusOne();main里判断:
    if(threadFlag.count==0){ //打印}else{ System.out.println("还有"+threadFlag.count+"个线程未完成!") wait();//等待}
      

  5.   

    你还可以把他包装成单例对象,设置多个记数器,对不同的线程类别进行不同记数classc threadFlag(){private static  threadFlag flag;private   int typeAcount;
    private   int typeBcount;
    private   int typeCount;
    private   int typeDcount;
    ...private threadFlag(){
    typeAcount=0;
    typeBcount=0;
    typeCcount=0;
    typeDcount=0;
    ..
    }public static synchronized threadFlag getInstance() {
    if ( flag == null ) flag = new threadFlag();
    return flag ;
    }public void addTypeAcount() {typeAcount++;}
    public void minusTypeAcount() {typeAcount--;}
    public int getTypeAcount(){return typeAcount;}
    ....public void clear(){
    typeAcount=0;
    typeBcount=0;
    typeCcount=0;
    typeDcount=0;
    ..
    }}不同类型的线程可以使用不同的记数器:
    你甚至可以给同一个类型的线程写一个父类,比如:
    class  TypeAThread implements Runnable {....
    public TypeAThread(){
    threadFlag.getInstance().addTypeAcount();
    }
    ..
    }
      

  6.   

    每个线程安装一个observor可以解决.
      

  7.   

    我说一个我的方法吧:大体思路: 用一个列表来记录正在跑的线程,线程结束的时候自己去把列表上自己的名字去掉,如 果列表上没东西了,就说明没有子线程在跑了.具体方法: 在主线程中new一个hashtable(),以每个线程的名字作为key,value就设为"alive"好了,启动线程的时候将这个hashtable()传给每个线程,每个线程run()方法的最后一行将自己在hashtable中的记录删除,主线程的最后地方用一个循环每隔一两秒去检查hashtable,如果
    hashtable里面没记录了,证明所有线程都执行完毕,然后再执行你想要的东西.
      

  8.   

    谢谢各位提供的思路!!我一会儿总结一下各位的思路写个程序,然后发表在我的blog中,欢迎大家去浏览!我的blog:http://blog.csdn.net/bryantd/
    另外怎么给分阿?
      

  9.   

    星空:
    我觉得按照你的思路,没有必要使用HashTable,只需要一个List就可以了。
    只要启动一个线程,就将其自身add到list中,执行完毕后将其从list中删除即可。
    最后检查list是否为空就好了。你说呢?
      

  10.   

    用hashtable的确话可以记录多种状态,当然楼主的问题用list就可以解决问题了.
      

  11.   

    我把源代码贴出来供大家指正。import java.util.*;class MyThread extends Thread{
    public static int count = 0;
    public static int amount = 0;
    private static Random rand = new Random();

    MyThread(int i){
    amount += rand.nextInt(i);
    }

    public void run(){
    ThreadControl.add(this);
    System.out.println("Number " + ++count +" thread: I am running.");
    try{
    sleep(200);
    }catch(InterruptedException e){}
    ThreadControl.del(this);
    }
    }public class ThreadControl extends Thread {
    private static List threadList = new ArrayList();

    public static synchronized void add(Thread t){
    threadList.add(t);
    }

    public static synchronized void del(Thread t){
    threadList.remove(t);
    }

    public static void main(String[] args) {
    long startTime = System.currentTimeMillis();

    while (MyThread.amount < 1000){
    new MyThread(10).start();
    }

    boolean over = false;
    while(!over){
    if (threadList.isEmpty()){
    over = true;
    System.out.println("There are " + MyThread.count + "threads running over.");
    System.out.println("The amount number is " + MyThread.amount);
    try{
    sleep(1000);
    }catch(InterruptedException e){}
    }
    }

    long endTime = System.currentTimeMillis();
    long interval = endTime- startTime;
    System.out.println("Time consumption: " + interval + " ms.");
    }}
      

  12.   

    bryantd:
    如果将run()方法中的sleep(200)改成sleep(20)的话,那么你的程序将会出错!
    所以为了保证稳定性应该将main()方法中的判断线程结束的if (threadList.isEmpty())改为
    if (MyThread.amount >= 1000 && threadList.isEmpty())
    不知你认为如何
      

  13.   

    我没有测试你的代码,但是我看你可能主要问题在于threadList.isEmpty()这句话有问题,
    ArrayList不是线程安全的,你应该在你的ThreadControl 里面加上一个synchronized的isEmpty方法。 
    同时我看这个问题应该是wait/notify的问题,不知道为什么诸位都不用,不理解,还望各位指教!
      

  14.   

    public static void main(String[] args){
        MyThread[] list = new MyThread[100];
        for(int i = 0; i < 100; i++){
            list[i] = new MyThread();
            list[i].start();
        }    for(int i = 0; i < 100; i++){
            list[i].join();
        }
        /*这里应该如何处理?*/
        System.out.println("线程全部执行完毕"); 
    }
      

  15.   

    我想问题确实是出在对threadList.isEmpty()的判断上,有可能出现这样的情况,当主线程
    创建完最后一个线程开始判断threadList.isEmpty()时,threadList为空,但最后创建的一个
    或多个线程还没有执行threadList.add(t),这时就会得出错误结果。
    如果将休眠时间设置得较长的话,那么就可以保证在主线程判断threadList.isEmpty()时
    threadList不为空。但如果休眠时间较短的话,那么上面的情况就有可能发生。主线程创建完最一个线程后马上执行threadList.isEmpty(),这时最后一个线程可能还在初始化并准备被系统调度执行的阶段,而其他的线程均已执行完毕。在ThreadControl 里面加上一个synchronized的isEmpty方法我觉没用,因为判断isEmpty
    只是主线程在做,并不涉及到同步的问题。
      

  16.   

    主线程不应该用sleep,换成wait
    当一个子线程结束的时候在notifyAll一下
      

  17.   

    To xjh_Love_paopao() 朋友,我同意的你的观点,你说的那种情况有可能发生。但是我觉得发生这种情况跟自线程的休眠时间没有关系,这只是一种十分凑巧的现象,也就是最后一个子线程创建以后,还没有执行ThreadControl.add(This)的时候,主线程恰好“醒来”,开始检测threadList.isEmpty()。
    有朋友说把threadList.isEmpty()套进一个synchronized方法,按照你的思路,因为问题的症结在于ThreadControl.add(This),所以还不如把ThreadControl.add(This)套在一个synchronzied方法中。
    但是我认为,上面两个解决办法都是不可行的!!!因为他们都没有避免xjh_Love_paopao()说的这种情况发生!!
    但是如果我的程序确实像你说的那样发生了错误,那上面两种办法应该至少可以避免错的发生,因为就像您说的,threadList.isEmpty()不是线程安全的,在检查其是否为空的时候,如果恰好某个线程执行了ThreadControl.add(This),可能会导致错误发生。不知道我理解得对不对?另外请朋友们用“wait - notify ”帮忙改一下我的程序,谢谢!
      

  18.   

    在 run()方法里面加个wait()就行了
     
    在100 条线城 执行完后,可以用notiflyall 来恢复线程
      

  19.   

    补充下
    还要在println上面加一sleep或者 join 语句
    println 执行后 用system.exit(0)退出
      

  20.   

    我记得用notifyall()的时候有个什么限制来着?
      

  21.   

    我想请问楼主,为什么“不能让这100线程全部join()”呢?
      

  22.   

    foxxiao111() 朋友,关于你说的wait - notify()方法,我是这么理解的:
    因为wait notify() 和 notifyall()方法不同于sleep(),它们要操作对象锁,所以应该放在同步代码快或者同步方法中进行调用。否则程序可能通过编译,但是运行的时候会产生一个IllegalMonitorStateException异常,关于这点,你可以参阅《Java编程思想(3er Edition)》中文版497页。而且也不是子线程调用wait()方法阿。另外我觉得这个问题根本不能用wait() - notify()方法来解决,逻辑上行不通。我是想在前面的所有子线程MyThread结束之后,由主线程来打印一些信息,而wait() - notify()的逻辑是:让某一线程处在等待状态,当外界条件改变时唤醒这个等待的线程。但是我的这个例子好像不太适用吧。如果大家觉得我说的不对,你们帮我改写一下代码,我看看怎么写。
      

  23.   

    我不知道是你们想简单了,还是我想复杂了!
    总之 我觉的要实现楼主的要求其实很简单!
    class Test extends Thread
    {
    public static void main(String[] args) throws InterruptedException
    {
    for(int i=0;i<100;i++)
    {
    Test test=new Test();
    test.start();
    }
    Thread.sleep(1);
    System.out.println("over");
    }

    public void run()
    {
    System.out.println(1);
    }
    }
    你们可以看看结果 它打印完所有的1之后 才打印 over!
      

  24.   

    class Test
    {
    public static void main(String[] args) throws InterruptedException
    {

    Threads test=new Threads();
    for(int i=0;i<100;i++)
    {
    new Thread(test).start();
    }
    Thread.sleep(1);
    System.out.println("over");
    }


    }class Threads implements Runnable
    {
    public void run() 
    {
    System.out.println(1);
    }}
    两个结果都一样!
      

  25.   

    我们用java解决实际问题。欢迎有经验的java程序员加入我们的讨论,因人数接近上限,初级人员暂时不能加入,请谅解。QQ 群:3001581
      

  26.   

    libonicky(开创世纪):
    我认为是您想简单了。您再好好看看我的代码就明白了。
      

  27.   

    如果你出了知道JAVA,还想知道其他语言,如C++,C,VB,SQL,C#的话,就请加入我们吧。我们欢迎高手!也欢迎出学者 QQ群:27856203
      

  28.   

    > 楼上的朋友,你仔细看一下我贴出来的代码,我的线程数目不是固定的。对不起,跟贴太多,看不太清楚了。请问楼主,这一贴是回答我上面“我想请问楼主,为什么“不能让这100线程全部join()”呢?”这个问题的吗?也许是我想简单了,但我真的不明白,把所有创建出来的线程都 join() 不行吗?package test;import java.util.ArrayList;
    import java.util.List;public class Test13 {    public static void main(String[] args) throws Exception {
            List<Thread> list = new ArrayList<Thread>();
            for (int i = 0; i < 100; i++) {
                Thread worker = new Thread() {
                    public void run() {
                        System.out.println(Thread.currentThread().getName());
                    }
                };
                worker.start();
                list.add(worker);
            }        /*这里就这么处理*/
            for (Thread worker : list) {
                worker.join();
            }        System.out.println("线程全部执行完毕");
        }}
      

  29.   

    To maquan('ma:kju):
    我认为您的方法很可能是不安全的。
    首先join()方法要放在try块中吧?
    我们线程的数目是不固定的,不是简单地100个。
    就算是线程数目固定,就是100个。您的程序也会有问题。
    因为线程创建后执行start()方法后,不能保证线程立即被执行,所以当创建线程的循环完成后,不一定每个线程都被装进了list中,所以最后的结果不一定准确!
      

  30.   

    join() 的API explain:Waits for this thread to die. 就是要等到该线程死亡才执行主线程的其他内容,那这和单线程有什么区别?
      

  31.   

    我在上贴给出的代码,只是为了说明 join() 是可以解决问题的,只是一个示例,所以,并没有按照“工业强度”的要求考虑各种特殊情况。1. 关于 try 块,当然应该有,但这不是本题目的核心问题,故简化了;2. 关于“100 个线程”,我给出的例子程序并不要求线程数固定是 100,你完全可以根据你的“业务逻辑”来确定线程数。不过有一点,每创建一个线程,就会有一个 Thread 对象记录在 list 里;3. 创建线程的循环完成后,所有创建出来的 Thread 对象一定会被装进 list 中(除非内存不足 :),不管这些 Thread 对象所代表的线程是不是真的“已经”开始执行,join() 一定会等到线程结束。(强调一下,Thread 对象并不是线程本身,而只是用于管理线程的一个 Object,list 里面放的是 Thread 对象,而不是“线程”。看到楼主可能对此有点误解,故强调一下)
    TO rikee19810706():
    先创建 100 个线程,然后再一个一个用 join() 去“等”,在你“等”的过程中,前面创建的那一大票线程都在忙着跑呢,这一点跟单线程完全不一样。如果是创建一个就用 join() 去“等”一个,那倒真跟单线程差不多了。  ;)
      

  32.   

     我的代码是在循环中实现多线程:
      ThreadClass c1 = new new ThreadClass();
      ThreadClass c2 = new new ThreadClass();  Thread t1 = new Thread();
      Thread t2 = new Thread();
       
      for(int i = 0,i<10,i++)
     {
         t1.start;
         t2.start;
         t1.join();
         t2.join();
         //.....
        sum = num1 + num2 +...........
     }
     按照楼上的各位意思,sum的求和应该在t1,t2线程终止才进行吧。
     可是我在单步调试到第二此循环的时候,就发生异常了:{java.lang.IllegalThreadStateException@1f8}
     请问问题在哪里?
      

  33.   

    同一个 Thread 对象,不能 start() 两次。for(int i = 0,i<10,i++)
     {
         Thread t1 = new Thread();
         Thread t2 = new Thread();
         t1.start;
         t2.start;
         t1.join();
         t2.join();
         //.....
        sum = num1 + num2 +...........
     }
      

  34.   

    楼主结账吧,jihanzhong(逍遥)  ,这位同学回答的多好呀!