本文共 5424 字,大约阅读时间需要 18 分钟。
如题:Java并发编程规则>有状态的线程安全对象在线程池中使用不一定就是线程安全的。在线程安全里面我们可以用的几个关键字是:volatile、Synchronized,另外状态变量我们可以使用原子变量。如果我们在编写了一个状态安全的线程类后,却不慎地使用非线程安全的线程池,那么也会导致线程不安全问题产生。
volatile的使用要求满足下面的两个条件:
1)对变量或者引用的写操作不依赖于变量或者引用的当前值(如果只有特定的单个线程修改共享变量,那么修改操作也是可以依赖于当前值); 2)该变量或者引用没有包含在其它的不变式条件中; volatile最常见的错误使用场景是使用volatile来实现并发 i++; 错误的原因是,该操作依赖于 i 变量的当前值,他是在 i 变量的当前值的基础上加一,所以说他依赖于 i 的当前值。多个线程执行 i++; 会丢失更新。比如两个线程同时读到 i 的当前值8,都进行加一,然后写回,最终 i 的结果是 9,而不是我们期待的10,丢失了更新。那么原子变量的引入就是针对volatile的这个缺陷的!!!原子变量的修改操作允许它依赖于当前值,所以说”原子变量“是比volatile的语义稍微强化一点!他不仅具有volatile的可见性,同时对原子变量。从Java 1.5开始引入了原子变量和原子引用:
java.util.concurrent.atomic.AtomicBoolean
java.util.concurrent.atomic.AtomicInteger
java.util.concurrent.atomic.AtomicLong
java.util.concurrent.atomic.AtomicReference
以及他们对应的数组:
java.util.concurrent.atomic.AtomicIntegerArray
java.util.concurrent.atomic.AtomicLongArray
java.util.concurrent.atomic.AtomicReferenceArray
注:synchronized关键字用的比较多,这里就不说明了。
package com.boonya.thread;import java.util.concurrent.TimeUnit;import java.util.concurrent.atomic.AtomicInteger;/** * 状态安全线程 * * @package com.boonya.thread.StateSafeThread * @date 2017年3月22日 下午4:28:57 * @author pengjunlin * @comment * @update */public class StateSafeThread extends Thread { private static AtomicInteger atomicCount = new AtomicInteger(0);// 多线程:线程安全的 private volatile static AtomicInteger volatileAtomicCount = new AtomicInteger(0);// 多线程:线程安全的 @Override public void run() { final Object lock = new Object(); for (int i = 0; i < 50000; i++) { new Thread(new Runnable() { @Override public void run() { synchronized (lock) { // Nothing.... } atomicCount.incrementAndGet(); volatileAtomicCount.incrementAndGet(); } }).start(); } // 休息5秒, 保证线程中的计算完成 try { TimeUnit.SECONDS.sleep(5); //关键 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println("Thread Name=====:"+this.getName()); System.out.println("线程并发执行对计数器累计5000次,看并发结果!"); System.out.println("atomicCount=" + atomicCount.get()); System.out.println("volatileAtomicCount=" + volatileAtomicCount.get()); }}
package com.boonya.thread;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.TimeUnit;import org.junit.Test;/** * 状态安全线程测试类 * * @package com.boonya.thread.StateSafeThreadTest * @date 2017年3月22日 下午4:41:37 * @author pengjunlin * @comment * @update */public class StateSafeThreadTest { /** * 线程安全的 * * @MethodName: testByOneThread * @Description: * @throws */ @Test public void testByOneThread(){ for (int i = 0; i < 5; i++) { Thread thread=new StateSafeThread(); thread.start(); } try { Thread.sleep(30000); } catch (InterruptedException e) { e.printStackTrace(); } } /** * 线程安全的 * * @MethodName: testByThreadPool * @Description: * @throws */ @Test public void testByThreadPool(){ Thread thread=null; ExecutorService executorService=Executors.newFixedThreadPool(5);// 线程个数大于或等于线程个数时线程安全 for (int i = 0; i < 5; i++) { thread=new StateSafeThread(); executorService.execute(thread); } /*Future future=executorService.submit(thread); try { System.out.println(future.get()); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (ExecutionException e1) { // TODO Auto-generated catch block e1.printStackTrace(); }*/ try { executorService.awaitTermination(30000, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { e.printStackTrace(); }finally{ executorService.shutdown(); } } /** * 非线程安全的 * * @MethodName: testByThreadPool2 * @Description: * @throws */ @Test public void testByThreadPool2(){ Thread thread=null; ExecutorService executorService=Executors.newFixedThreadPool(3);// 小于线程个数导致线程不安全 for (int i = 0; i < 5; i++) { thread=new StateSafeThread(); executorService.execute(thread); } /*Future future=executorService.submit(thread); try { System.out.println(future.get()); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (ExecutionException e1) { // TODO Auto-generated catch block e1.printStackTrace(); }*/ try { executorService.awaitTermination(30000, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { e.printStackTrace(); }finally{ executorService.shutdown(); } } /** * 线程安全的 * * @MethodName: testByThreadPool3 * @Description: * @throws */ @Test public void testByThreadPool3(){ Thread thread=null; ExecutorService executorService=Executors.newCachedThreadPool(); for (int i = 0; i < 5; i++) { thread=new StateSafeThread(); executorService.execute(thread); } /*Future future=executorService.submit(thread); try { System.out.println(future.get()); } catch (InterruptedException e1) { // TODO Auto-generated catch block e1.printStackTrace(); } catch (ExecutionException e1) { // TODO Auto-generated catch block e1.printStackTrace(); }*/ try { executorService.awaitTermination(30000, TimeUnit.MILLISECONDS); } catch (InterruptedException e) { e.printStackTrace(); }finally{ executorService.shutdown(); } }}注:可以测试运行查看结果,推荐使用缓存线程池。
转载地址:http://jeyu.baihongyu.com/