我尝试在10次循环中创建10个线程,并且希望在我没有为方法分配synchronized时看到冲突打印出来。 这是我的代码
public class SingletonService {
private static SingletonService singleton = null;
public static SingletonService getInstance() {
if (singleton == null) {
synchronized(SingletonService.class) {
if (singleton == null) {
singleton = new SingletonService();
return singleton;
}
}
}
return singleton;
}
public void testMethod() {
boolean flag = true;
System.out.println("start");
if (flag == false) {
System.out.println(">>>>>>>>>>>>>>>Error");
}
flag = false;
System.out.println("over");
}
}
以下是获取服务并调用testMethod()
的线程public class Transferable extends Thread {
private SingletonService service = null;
public Transferable(SingletonService aService) {
service = aService;
}
public void run() {
System.out.println("Service Start");
service.testMethod();
System.out.println("Service End");
}
}
现在让我很困惑的是,当我尝试在像
这样的循环中创建线程时for (int i = 0; i < 10; i ++) {
Transferable t1 = new Transferable(service);
t1.run();
Thread.sleep(10);
}
然后服务中的callMethod()将顺序执行,不会相互影响(也不会抛出错误消息)
但是当我尝试手动创建线程时,如
Transferable t1 = new Transferable(service);
Transferable t2 = new Transferable(service);
Transferable t3 = new Transferable(service);
Transferable t4 = new Transferable(service);
Transferable t5 = new Transferable(service);
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
打印出错误信息,开始结束序列也变得无序...... 任何人都可以帮助解决我的问题告诉细节? 感谢^ BR
答案 0 :(得分:2)
有很多因素会影响两个例子的行为。
首先,SingletonService.testMethod()
将flag
定义为局部变量。因此,它不能真正用作检查线程冲突的标志。我不知道你怎么会得到一个错误输出。该标志应该是一个字段。
其次,循环示例调用线程的run()
方法,而手动示例调用start()
方法。 start()
将创建一个新线程,该线程将依次调用run()
方法。 run()
只会在当前主题中执行Transferable.run()
方法,从而强制执行顺序操作。
第三,如果你改变了前面提到的东西,你仍然会在每个循环中进行Thread.sleep(10)
调用,这意味着在启动一个线程和下一个线程之间,你需要等待10毫秒,这对于第一个线程完成。
答案 1 :(得分:1)
查看Thread java se文档站点 https://docs.oracle.com/javase/8/docs/api/java/lang/Thread.html,特别是start()方法
start():使该线程开始执行; Java虚拟机调用此线程的run方法。
在循环中调用run()并不会导致Thead执行。相反,run()在主线程中执行,这就是为什么执行是顺序的,而不是像你期望的那样并行。
请尝试在for循环中用start()替换run()。