java 笔记: concurrency 之 synchronization

1. 当某个method需要同步访问时, 可以用synchronized来修饰

import static org.junit.Assert.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import org.junit.Assert;
import org.junit.Test;


public class Test_Callable implements MyResource {

	public static void main(String[] args) {
		try {
			(new Test_Callable()).test();
		} catch(Exception ex) {
			System.out.println("Error in test");
		}
	}
	@Test
	public void test() throws InterruptedException, ExecutionException {
		System.out.println("Begin Test!");
		int nThreadCnt=100;
		ExecutorService service = Executors.newCachedThreadPool();
		for (int i=0;i<nThreadCnt;i++) {
			service.submit(new CallableJob(i, this));
		}
		//shutdown() will wait all the task to complete first
		service.shutdown();
		System.out.println("End Test!");
	}

	@Override
	public synchronized int Calculate(int id) throws Exception {
		int nResource  = resourceNum;
		nResource +=2;
		resourceNum = nResource;
		TimeUnit.SECONDS.sleep(1);
		if (nResource != resourceNum )
			throw new Exception("Sync problem in job " + id);
		return resourceNum;
	}

	private int resourceNum=0;
}

interface MyResource {
	int Calculate(int id) throws Exception;
}
class CallableJob implements Callable<String> {

	public CallableJob(int id, MyResource r) {
		this.id = id;
		this.r = r;
	}
	private int id ;
	private MyResource r;
	private int seed =Math.abs((new Random()).nextInt()) % 10;
	@Override
	public String call(){
		System.out.println("Begin job " + this.id);
		try
		{
			r.Calculate(this.id);
		}
		catch(Exception ex) {
			System.out.println("Exception:" + ex.getMessage());
		}
		System.out.println("End job " + this.id);
		return String.format("%s", this.seed);
	}
}

 

 

 

当多个method需要访问呢一个资源时, 用lock

	private Lock lock=new ReentrantLock();
	@Override
	public int Calculate(int id) throws Exception {
		int nResource  = resourceNum;
		nResource +=2;
		lock.lock();
		try {
			resourceNum = nResource;
			TimeUnit.SECONDS.sleep(1);
			if (nResource != resourceNum )
				throw new Exception("Sync problem in job " + id);
		} finally {
			lock.unlock();
		}
		return resourceNum;
	}

 

Atomic* classes

 

	public int Calculate(int id) throws Exception {
		
		int nResource  = resourceNum.addAndGet(2);
		return nResource;
	}

	private AtomicInteger resourceNum=new AtomicInteger();

 

    check package java.util.concurrent.atomic for more Atomic classes

Use critical sections:

 

	public int Calculate(int id) throws Exception {
		
		int nResource  = 0;
		synchronized(this) {
			nResource = this.resourceNum +2;
			Thread.yield();
			this.resourceNum = nResource;
			Thread.yield();
			if (nResource != this.resourceNum)
				throw new Exception ("Synchronized error");
		}
		return nResource;
	}

 

ThreadLocal<> storage

 

	public int Calculate(int id) throws Exception {
		if (null == resourceNum) {
			resourceNum = new ThreadLocal<Integer>();
		}
		int nResource  = 0;
		if (this.resourceNum.get() == null)
			this.resourceNum.set(0);
		this.resourceNum.set(this.resourceNum.get() + 2);
		nResource = this.resourceNum.get();
		System.out.println("resource value in ThreadLocal is " + nResource);
		return nResource;
	}

	private ThreadLocal<Integer> resourceNum=new ThreadLocal<Integer>();
Note, the output of resource value will always be 2 due to it’s  ThreadLocal

posted on 2012-03-04 21:06  learner  阅读(987)  评论(0)    收藏  举报

导航