Java ExecutorService 和同步

标签 java multithreading executorservice java.util.concurrent

我试图了解 ExecutorService 以及它将如何避免使用同步关键字。我尝试了下面类似的操作(为了清楚起见,避免导入),但给出了错误的结果:

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 并行运行作业,但不会自动确保跨线程并发访问共享状态的安全性。所以,你的问题的两个部分都是"is"。

  1. 该问题的部分原因是两个可运行对象共享相同的 FinTrans 状态对象。
  2. 问题的另一部分是缺乏对共享状态的访问的任何同步或其他原子保证。

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

关于Java ExecutorService 和同步,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27519301/

相关文章:

java - 暂停和恢复 ExecutorService 或关闭并重新启动 Java Executor 服务

java - 将方法提交到 ExecutorService Java

java - 动画构造函数在 Java GUI 中不起作用

java - CipherInputStream 如何为您正在读取的不同字节打开/关闭密码

java - 将 100 到 1000 之间可被 5 和 6 整除的数字相加

java - 是否可以在已安排作业的tomcat中部署jar?

java - Executors.newFixedThreadPool 挂起的线程

C++ shared_ptr 和 threadsanizer 报告数据争用

java - 在多线程中使用 easymock

java - 当新线程运行时更大的线程池或额外的 ExecutorService?