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
浙公网安备 33010602011771号