我的预期输出是
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();
}
}
}
答案 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()方法使一个线程的执行到另一个线程的执行结束。
答案 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" ) ;
}