public abstract class IntGenerator { private volatile boolean canceled = false; public abstract int next( ); public void cancle( ) { canceled = true; } public boolean isCanceled( ) { return canceled; } }
public class EvenChecker implements Runnable { private IntGenerator generator; private final int id; public EvenChecker(IntGenerator g , int ident) { generator = g; id = ident; } public void run() { while( !generator.isCanceled() ) { int val = generator.next(); if(val % 2 != 0) { System.out.println(val + "not even!"); generator.cancle(); } } } public static void test(IntGenerator gp, int count) { System.out.println("Press Control -C to exit"); ExecutorService exec = Executors.newCachedThreadPool(); for(int i = 0; i < 10;i++) exec.execute(new EvenChecker(gp, i)); exec.shutdown(); } public static void test(IntGenerator gp) { test(gp, 10); } }
public class EvenGenerator extends IntGenerator { private int currentEvenValue = 0; public int next() { ++currentEvenValue; ++currentEvenValue; return currentEvenValue; } public static void main(String []args) { EvenChecker.test(new EvenGenerator()); } }
在使用并发时,将域设置为private是很重要的。这是一种保证。保证没有其它任务能够直接訪问到该域。
JVM负责跟踪对象被加锁的次数。假设一个对象被解锁(即锁被全然释放),其计数变为0。
假设对该资源的訪问是复合操作,即使共享对象自身是线程安全的,也无法保证数据的一致性,比如:if( put(**))这样的操作。就必需要把复合操作所有包括在锁内,对于存在多个对象的共享。假设相互之间有状态的关联,这样的处理方式依旧有效。
public class SynchronizedEvenGenerator extends IntGenerator { private int currentEvenValue = 0; @Override public synchronized int next() { ++currentEvenValue; Thread.yield(); ++currentEvenValue; return currentEvenValue; } public static void main(String[] args) { EvenChecker.test(new SynchronizedEvenGenerator()); } }
public class MutexEvenGenerator extends IntGenerator { public int currentEvenValue = 0; private Lock lock = new ReentrantLock(); @Override public int next() { lock.lock(); try { ++currentEvenValue; ++currentEvenValue; return currentEvenValue; } finally { lock.unlock(); } } public static void main(String []args) { EvenChecker.test( new MutexEvenGenerator( )); } }
当你在使用Lock对象时,有一些原则须要被记住:你必须放置在finally子句中带有unlock()的try-finally语句,以避免该锁被无限期锁住。
注意,return语句必须在try子句中出现,以确保unlock()不会过早发生,从而将数据暴露给第二个任务。
public class MyMutexTest { private static Lock lock = new ReentrantLock(); public static void main(String args[]) { new Thread( new Runnable() { public void run() { lock.lock(); while(true); } }).start(); new Thread(new Runnable() { public void run() { if( lock.tryLock() == false ) { System.out.println("acquire lock failed 1"); } } }).start();; new Thread( new Runnable() { public void run() { try { if(lock.tryLock(2, TimeUnit.SECONDS) == false) { System.out.println("acquire lock failed 2"); }} catch (InterruptedException e) { } } }).start(); } }
public class MyVisibilityTest implements Runnable{ private static boolean mv = false; private static int integer = 0; @Override public void run() { while(true) { if(mv == true) { System.out.println(integer); return; } } } public static void main(String []args) { new Thread(new MyVisibilityTest()).start(); integer = 34; mv = true; } }
假设在仅仅共享一个对象的前提下。它为你提供了一种将线程间的复合操作转为线程安全操作的机会。
public class AtomicEvenGenerator extends IntGenerator { private AtomicInteger currentEvenValue = new AtomicInteger(0); public int next() { return currentEvenValue.addAndGet(2); } public static void main(String args[]) { EvenChecker.test(new AtomicEvenGenerator()); } }
sychronized如何才干不使用额外的一个对象进行加锁?办法就是对this加锁,假设多个线程运行的是同一任务,使用sychronized是不错的选择。由于它能够避免你显式的定义和使用一个Lock。
class ContextThread { private static ThreadLocal<Integer> value = new ThreadLocal<Integer>(); public static void setInteger(Integer value){ ContextThread.value.set(value); } public static Integer getInteger() { return value.get(); } public static void increment() { value.set(value.get() + 1); } } public class ThreadLocalTest { public static void main(String []args) { for(int i = 0; i < 5; i++) { new Thread(new Runnable() { @Override public void run() { ContextThread.setInteger(0); ContextThread.increment(); System.out.println( ContextThread.getInteger() ); } }).start(); } } }
原文:http://www.cnblogs.com/gcczhongduan/p/5153692.html