我试图了解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/

10-11 04:55