首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Java ExecutorService与同步

Java ExecutorService与同步
EN

Stack Overflow用户
提问于 2014-12-17 06:06:10
回答 2查看 2.5K关注 0票数 1

我正在努力理解ExecutorService,以及它将如何避免使用同步关键字。我尝试了这样的方法(为了清晰起见,避免进口),结果是错误的:

代码语言:javascript
复制
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);
           }
      }
   }
}

这给了我错误的结果:

代码语言:javascript
复制
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.这是因为两个运行库共享同一个FinTrans对象吗? 2.这是否意味着我们在这里也需要相同的旧同步机制?

我试图了解在什么情况下我们可以使用ServiceExecutors

阿南德

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-12-17 06:08:46

ExecutorService并行运行作业,但不会自动安全地跨线程并发访问共享状态。所以,对你问题的两个部分都说“是的”。

  1. 这个问题部分是由共享同一个FinTrans状态对象的两个运行程序造成的。
  2. 问题的另一部分是在访问共享状态时缺乏任何同步或其他原子保证。

执行器很适合异步提交任务,并且能够通过返回的Future实例检查它们的状态(例如,它们是否已经完成)。

票数 2
EN

Stack Overflow用户

发布于 2014-12-17 06:18:06

在异步处理的情况下,需要有同步块。如果您试图模拟银行帐户,使用java进行处理,例如,您可以使用一些java并发原语。

使用AtomicDouble,您可以这样做:

代码语言:javascript
复制
class FinTrans {
   final private AtomicDouble amount = new AtomicDouble();

   public void debit(double debit) {
      double current = 0;
      double new = 0;
      do {
         current = amount.get();
         new = current + debit;
      } while (!amount.compareAndSet(current, newAmount));
   }

   public void credit(double credit) {
     debit(- credit);
   }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27519301

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档