Java AtomicIntegerクラスの使用方法の詳細

5059 ワード

まず、2つのコードを見てみましょう.1つはIntegerで、1つはAtomicIntegerです.以下です.

public class Sample1 {
  private static Integer count = 0;
  synchronized public static void increment() {
    count++;
  }
}

以下はAtomicIntegerのものです.

public class Sample2 {
  private static AtomicInteger count = new AtomicInteger(0);
  public static void increment() {
    count.getAndIncrement();
  }
}

以上の2つのコードは、Integerを使用する場合、synchronizedを付けて同時スレッド同時アクセスが発生しないことを保証しなければならないが、AtomicIntegerではsynchronizedを付けなくてもよい.ここでAtomicIntegerは原子操作を提供しているので、以下で説明する.
AtomicIntegerの紹介
AtomicIntegerは原子操作を提供するIntegerクラスで、スレッドの安全な方法で操作を加減します.
AtomicInteger使用シーン
AtomicIntegerはIntegerの使用のために原子操作を提供するので,高同時性の場合の使用に適している.
AtomicIntegerソースセクションの説明

public class AtomicInteger extends Number implements java.io.Serializable {
  private static final long serialVersionUID = 6214790243416807050L;
  // setup to use Unsafe.compareAndSwapInt for updates
  private static final Unsafe unsafe = Unsafe.getUnsafe();
  private static final long valueOffset;
  static {
    try {
      valueOffset = unsafe.objectFieldOffset
        (AtomicInteger.class.getDeclaredField("value"));
    } catch (Exception ex) { throw new Error(ex); }
  }
  private volatile int value;

以上がAtomicIntegerのソースコードの一部であるが、ここではvalueについて述べる.ここでvalueはvolatileキーワードを使用している.volatileはここでできる役割は複数のスレッドが変数を共有できるようにすることであるが、問題はvolatileを使用するとVM最適化が機能しなくなり、効率が低下するため、必要なときに使用することである.そのためAtomicIntegerクラスは勝手に使わず、使用シーンで使用します.
AtomicIntegerインスタンスの使用
以下に、マルチスレッドの場合、AtomicIntegerを使用する例を示します.このコードは、ITオタクのコードを借りたものです.

 public class AtomicTest {
  static long randomTime() {
    return (long) (Math.random() * 1000);
  }
  public static void main(String[] args) {
    //     ,   100   
    final BlockingQueue queue = new LinkedBlockingQueue(100);
    //    
    final ExecutorService exec = Executors.newFixedThreadPool(5);
    final File root = new File("D:\\ISO");
    //     
    final File exitFile = new File("");
    //     ,   
    // AtomicInteger               ,     synchronized,       。
    final AtomicInteger rc = new AtomicInteger();
    //     ,   
    final AtomicInteger wc = new AtomicInteger();
    //    
    Runnable read = new Runnable() {
      public void run() {
        scanFile(root);
        scanFile(exitFile);
      }
      public void scanFile(File file) {
        if (file.isDirectory()) {
          File[] files = file.listFiles(new FileFilter() {
            public boolean accept(File pathname) {
              return pathname.isDirectory() || pathname.getPath().endsWith(".iso");
            }
          });
          for (File one : files)
            scanFile(one);
        } else {
          try {
            //      incrementAndGet  ,           1,      
            int index = rc.incrementAndGet();
            System.out.println("Read0: " + index + " " + file.getPath());
            //         
            queue.put(file);
          } catch (InterruptedException e) {
          }
        }
      }
    };
    // submit       Runnable       ,            Future。
    exec.submit(read);
    //      
    for (int index = 0; index < 4; index++) {
      // write thread
      final int num = index;
      Runnable write = new Runnable() {
        String threadName = "Write" + num;
        public void run() {
          while (true) {
            try {
              Thread.sleep(randomTime());
              //      incrementAndGet  ,           1,      
              int index = wc.incrementAndGet();
              //            ,             (     )。
              File file = queue.take();
              //        
              if (file == exitFile) {
                //     "  ",          
                queue.put(exitFile);
                break;
              }
              System.out.println(threadName + ": " + index + " " + file.getPath());
            } catch (InterruptedException e) {
            }
          }
        }
      };
      exec.submit(write);
    }
    exec.shutdown();
  }
}

AtomicInteger使用概要
AtomicIntegerは、非ブロックアルゴリズムを使用して同時制御を実現しており、いくつかの高同時プログラムでは非常に適していますが、各シーンが適しているわけではありません.異なるシーンでは、異なる数値クラスを使用します.
以上、Java AtomicIntegerクラスの使い方について詳しく説明したすべての内容であり、皆さんの役に立つことを願っています.興味のある方は、javaオリジナルシーケンス化とKryoシーケンス化の性能例の比較分析、Javaエンタープライズクラスのプロジェクト開発思想、Java mapについて配列を保存し、値コードを取り出して詳しく説明するなど、何か問題があればいつでも伝言してください.