我试图了解ExecutorService以及它将如何避免使用synced关键字。我在下面尝试了类似的操作(为清楚起见,避免导入),结果却是错误的:
public class ReadWebPage
{
public static void main(String[] args)
{
ExecutorService executor = Executors.newFixedThreadPool(5);
FinTrans ft = new FinTrans ();
TransThread tt1 = new TransThread (ft, "Deposit Thread");
TransThread tt2 = new TransThread (ft, "Withdrawal Thread");
executor.submit(tt2);
executor.submit(tt1);
executor.shutdown();
}
}
class FinTrans
{
public static String transName;
public static double amount;
}
class TransThread implements Runnable
{
private FinTrans ft;
private String name;
TransThread (FinTrans ft, String name)
{
this.name = name;
this.ft = ft;
}
public String getName(){
return name;
}
public void run ()
{
for (int i = 0 ; i < 10 ; i++ )
{
if (getName ().equals ("Deposit Thread"))
{
ft.transName = "Deposit";
try
{
Thread.sleep ((int) (Math.random () * 100));
}
catch (InterruptedException e)
{
}
ft.amount = 2000.0;
System.out.println (ft.transName + " " + ft.amount);
}
else
{
ft.transName = "Withdrawal";
try
{
Thread.sleep ((int) (Math.random () * 10));
}
catch (InterruptedException e)
{
}
ft.amount = 250.0;
System.out.println (ft.transName + " " + ft.amount);
}
}
}
}
这给了我错误的结果:
Deposit 250.0 //wrong
Withdrawal 250.0
Withdrawal 250.0
Withdrawal 250.0
Withdrawal 250.0
Withdrawal 250.0
Withdrawal 250.0
Withdrawal 250.0
Withdrawal 250.0
Withdrawal 2000.0 //wrong
Deposit 250.0 //wrong
Deposit 2000.0
Deposit 2000.0
Deposit 2000.0
Deposit 2000.0
Deposit 2000.0
Deposit 2000.0
Deposit 2000.0
Deposit 2000.0
Deposit 2000.0
您能否解释一下这里出了什么问题?
1.是否因为两个Runnable共享同一个FinTrans对象?
2.这是否意味着我们在这里也需要相同的旧同步机制?
我试图了解在什么情况下我们可以使用ServiceExecutors
阿南德
最佳答案
ExecutorService并行运行作业,但不能自动确保跨线程并发访问共享状态的安全性。因此,对问题的两个部分都“是”。
造成此问题的部分原因是两个可运行对象共享相同的FinTrans
状态对象。
问题的另一部分是缺少对访问该共享状态的任何同步或原子保证。
执行程序非常适合异步提交任务,并能够通过返回的Future
实例检查其状态(例如,它们是否完成)。
关于java - Java ExecutorService和同步,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27519301/