在循环中使用线程,如何在到达主程序结束之前完成循环?

时间:2012-10-07 13:52:24

标签: java multithreading

我的预期输出是

Count : 1
Count : 2
Count : 3
Count : 4
Count : 5

我尝试过synchronized和Lock但它们都不起作用。我到达

  

结束主要

比我完全完成循环更快。目前的输出是:

Starting Main
Count : 1
Count : 2
Count : 3
Count : 4
Ending Main
Count : 5

任何想法为什么Count:5是在Ending Main之后?这是我的代码:

public class Demo {
    public static void main( String [] args ) {
        System.out.println( "Starting Main" ) ;
        for ( int i = 1 ; i <= 5 ; i++ ) {
            Thread numberThread = new Thread(new NumberTask(i)) ;
            numberThread.start() ;
        }
        System.out.println( "Ending Main" ) ; 
    }
}

class NumberTask implements Runnable {
    private Lock bankLock = new ReentrantLock();
    int count ;
    public NumberTask( int count ) {
        this.count = count ;
    }

    synchronized public void run() {
        bankLock.lock();
        try {
            System.out.println( "Count : " + count ) ;
        } finally {
            bankLock.unlock();
        }
    }
}

3 个答案:

答案 0 :(得分:1)

  

任何想法为什么“Count:5”在“Ending Main”之后?

当线程启动时,无法保证它立即开始运行。在新线程初始化时,分叉新线程的线程继续运行是正常的。因此,在主线程启动第5个线程后,它继续运行并将线程打到System.out.println("Ending Main");语句。

重要的是要意识到线程的全部意义在于它们以异步方式运行。因为线程可以在并发运行的单独CPU /核上进行调度,所以通常很难预测线程程序中的操作顺序。例如。由于thread race conditions,您可能会在“计数1”之前看到“计数2”打印。我刚开始运行500个线程,我看到了:

Count : 128
Count : 130
Count : 129
Count : 131

此外,由于您的bankLock类属于NumberTask类,因此它不会在线程之间锁定。您可以将锁定静态到NumberTask以使每个类有一个锁,或者您可以在main中实例化锁并将其传递给NumberTask构造函数。你真的不需要锁定,因为System.out是一个PrintStram synchronized对象。 synchronized run()方法也是如此。由于您将在NumberTask实例上进行同步,因此它不会执行任何操作,因为没有其他线程将在同一对象上进行同步。

答案 1 :(得分:0)

执行线程是不可预测的,因此您会遇到此行为。使用join()方法使一个线程的执行到另一个线程的执行结束。

请阅读Java thread unpredictable

答案 2 :(得分:0)

您可以使用join()等待其他线程完成。您的代码需要更新如下:

public static void main( String [] args ) {

    System.out.println( "Starting Main" ) ;
        Thread numberThread;
        for ( int i = 1 ; i <= 5 ; i++ ) {
            numberThread = new Thread(new NumberTask(i)) ;
            numberThread.start() ;
        }
        numberThread.join();
        System.out.println( "Ending Main" ) ; 
    }