我编写了一个程序,其中运行了两个线程,这就是我使用synchronized关键字的原因。我的代码在下面 -
public class TestThreadAnother {
public synchronized void decrement(){
try {
for (int i = 4; i > 0; i--) {
System.out.println("Thread " + i);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class TestThreadClass extends Thread {
private String threadName;
TestThreadAnother obj1;
public TestThreadClass(String threadName, TestThreadAnother Obj1) {
this.threadName = threadName;
obj1 = Obj1;
System.out.println("Creating " + threadName);
}
@Override
public void run() {
System.out.println("Running " + threadName);
obj1.decrement();
System.out.println("End of " + threadName);
}
}
public class TestThreadMain {
public static void main(String[] args) {
TestThreadAnother obj1 = new TestThreadAnother();
TestThreadClass t1 = new TestThreadClass("Thread 1", obj1);
TestThreadClass t2 = new TestThreadClass("Thread 2", obj1);
t1.start();
t2.start();
}
}
输出应该是 -
Creating Thread 1
Creating Thread 2
Running Thread 1
Thread 4
Thread 3
Thread 2
Thread 1
End of Thread 1
Running Thread 2
Thread 4
Thread 3
Thread 2
Thread 1
End of Thread 2
但我得到以下结果 -
Creating Thread 1
Creating Thread 2
Running Thread 2
Thread 4
Thread 3
Running Thread 1
Thread 2
Thread 1
Thread 4
Thread 3
Thread 2
Thread 1
End of Thread 1
End of Thread 2
但我的问题是因为我使用的是同步方法然后为什么会发生这种情况?因为知道我是否使用synchronized,所以在第一个线程将执行然后第二个将执行。但在我的情况下,有时这不会发生。 Java专家需要您就此问题提供帮助。
答案 0 :(得分:11)
输出正确。仅同步您的decrement()
方法。这意味着此对象的decrement()
方法一次不能被多个线程调用。但是,当一个线程执行decrement()
时,这并不妨碍其他线程做其他事情。
您的输出显示当线程2正在执行decrement()
时,线程1正在执行System.out.println()
方法中的第一个run()
,然后可能等待线程2完成其调用decrement()
,然后执行decrement()
。
答案 1 :(得分:5)
您必须了解的重要事项是。 Synchronization
仅保证两个线程不会同时锁定同一对象。在您的情况下,一个线程(thread2或thread1)将获得锁定并将调用decrement()
方法。直到此线程结束,其他threda将被阻止。
现在,分析你的输出:
Creating Thread 1
Creating Thread 2
Running Thread 2 // Thread -2 has the lock now.
Thread 4 // thrad-2's decrement()
Thread 3
Running Thread 1 // thread-1 is blocked. So, only this line is printed
Thread 2 // still thread2
Thread 1 // still thread2
Thread 4 // now thread1 decrement() starts
Thread 3
Thread 2
Thread 1
End of Thread 1
End of Thread 2
在你的减量方法中打印thread.getName()
以获得更好的想法。
答案 2 :(得分:3)
你应该这样做,
@Override
public void run() {
synchronized(obj1){
System.out.println("Running " + threadName);
obj1.decrement();
System.out.println("End of " + threadName);
}
}
方法可以是非同步的
public void decrement(){
try {
for (int i = 4; i > 0; i--) {
System.out.println("Thread " + i);
}
} catch (Exception e) {
e.printStackTrace();
}
}
答案 3 :(得分:2)
这是因为以下两行不在同步块中:
System.out.println("Running " + threadName);
System.out.println("End of " + threadName);
所以在递减之前和之后()可以切换线程。如果您想要预期的观察,您可以修改如下的减量方法:
public synchronized void decrement(String threadName ){
System.out.println("Decrement: " + threadName);
try {
for (int i = 4; i > 0; i--) {
System.out.println("Thread " + i);
}
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("End Decrement: " + threadName);
}
更改下面的运行方法,
public void run() {
obj1.decrement(threadName);
}
答案 4 :(得分:2)
其他答案已经解释了为什么synchronized
没有按预期工作。这更像是评论的后续行动:
仍然不能保证我的线程1先执行然后再执行2
你可以在第一个使用join
来处理线程的外部:
t1.start(); // Start t1
t1.join(); // Wait for t1 to complete
t2.start(); // Start t2
如果您需要主线程继续执行,而线程一次运行一个,您可以创建一个管理器线程来执行它们。幸运的是,已有人did this for us:
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.execute(t1);
executor.execute(t2);
public static ExecutorService newSingleThreadExecutor()
创建一个使用单个工作线程执行无限制的执行程序 队列。 (但请注意,如果此单个线程由于a而终止 在关机之前执行失败,一个新的将采取它 如果需要执行后续任务,则放置。)保证任务按顺序执行,并且在任何给定时间不会有多个任务处于活动状态。
(强调我的)
答案 5 :(得分:0)
从“运行...”和“运行结束......”System.out.println
以及decrement()
方法不在原子操作中
如果你想坚持使用同步方法:
只需输入
System.out.println("Running " + threadName);
和
System.out.println("End of " + threadName);
在decrement()
方法中,我认为您将能够获得所需的输出。