Synchronized修饰的方法叫做同步方法。在java中每个对象都有一把锁(lock)或者叫做监视器。这里做一些比较,看一下作用范围。
首先创建一个实体类,声明2个同步方法和2个静态同步方法。
public class SyncEntity {
private String name;
public SyncEntity(String name) {
this.name = name;
}
/**
* 非同步方法1
*/
public void getFood() {
try {
System.out.println(name + " getFood-" + DateUtils.formatDate(new Date()));
Thread.sleep(5000);
System.out.println(name + " returnFood-" + DateUtils.formatDate(new Date()));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 非同步方法2
*/
public void getMoney() {
try {
System.out.println(name + " getMoney-" + DateUtils.formatDate(new Date()));
Thread.sleep(5000);
System.out.println(name + " returnMoney-" + DateUtils.formatDate(new Date()));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 同步方法1
*/
public synchronized void getBook() {
try {
System.out.println(name + " getBook-" + DateUtils.formatDate(new Date()));
Thread.sleep(5000);
System.out.println(name + " returnBook-" + DateUtils.formatDate(new Date()));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 同步方法2
*/
public synchronized void getPen() {
try {
System.out.println(name + " getPen-" + DateUtils.formatDate(new Date()));
Thread.sleep(5000);
System.out.println(name + " returnPen-" + DateUtils.formatDate(new Date()));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 静态同步方法1
*/
public synchronized static void getStaticCar(String name) {
try {
System.out.println(name + " getStaticCar-" + DateUtils.formatDate(new Date()));
Thread.sleep(5000);
System.out.println(name + " returnStaticCar-" + DateUtils.formatDate(new Date()));
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* 静态同步方法2
*/
public synchronized static void getStaticBus(String name) {
try {
System.out.println(name + " getStaticBus-" + DateUtils.formatDate(new Date()));
Thread.sleep(5000);
System.out.println(name + " returnStaticBus-" + DateUtils.formatDate(new Date()));
} catch (Exception e) {
e.printStackTrace();
}
}
}
测试不同线程执行同步代码块
// 创建一个对象
SyncEntity syncEntity = new SyncEntity("TestSync");
// 创建一个线程池,这里用固定线程数量的
ExecutorService executorService = new ThreadPoolExecutor(2,2,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<>(), new ThreadFactoryBuilder().setNameFormat("自定义线程名称-%d").build());
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName()+" 开始执行。。。");
synchronized (syncEntity){
syncEntity.getFood();
}
});
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName()+" 开始执行。。。");
synchronized (syncEntity){
syncEntity.getMoney();
}
});
// 关闭线程池
executorService.shutdown();
执行结果
自定义线程名称-0 开始执行。。。
自定义线程名称-1 开始执行。。。
TestSync getFood-Thu, 17 Oct 2019 10:09:37 GMT
TestSync returnFood-Thu, 17 Oct 2019 10:09:42 GMT
TestSync getMoney-Thu, 17 Oct 2019 10:09:42 GMT
TestSync returnMoney-Thu, 17 Oct 2019 10:09:47 GMT
结论:同步代码块锁定传入对象
测试不同线程执行同一对象上的同一方法
// 创建一个对象
SyncEntity syncEntity = new SyncEntity("TestSync1");
// 创建一个线程池,这里用固定线程数量的
ExecutorService executorService = new ThreadPoolExecutor(2,2,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<>(), new ThreadFactoryBuilder().setNameFormat("自定义线程名称-%d").build());
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName()+" 开始执行。。。");
syncEntity.getBook();
});
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName()+" 开始执行。。。");
syncEntity.getBook();
});
// 关闭线程池
executorService.shutdown();
执行结果
自定义线程名称-0 开始执行。。。
自定义线程名称-1 开始执行。。。
TestSync getBook-Thu, 17 Oct 2019 09:11:28 GMT
TestSync returnBook-Thu, 17 Oct 2019 09:11:33 GMT
TestSync getBook-Thu, 17 Oct 2019 09:11:33 GMT
TestSync returnBook-Thu, 17 Oct 2019 09:11:38 GMT
测试不同线程执行同一对象上的不同方法
// 创建一个对象
SyncEntity syncEntity = new SyncEntity("TestSync1");
// 创建一个线程池,这里用固定线程数量的
ExecutorService executorService = new ThreadPoolExecutor(2,2,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<>(), new ThreadFactoryBuilder().setNameFormat("自定义线程名称-%d").build());
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName()+" 开始执行。。。");
syncEntity.getBook();
});
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName()+" 开始执行。。。");
syncEntity.getBook();
});
// 关闭线程池
executorService.shutdown();
执行结果
自定义线程名称-0 开始执行。。。
自定义线程名称-1 开始执行。。。
TestSync getBook-Thu, 17 Oct 2019 09:38:43 GMT
TestSync returnBook-Thu, 17 Oct 2019 09:38:48 GMT
TestSync getPen-Thu, 17 Oct 2019 09:38:48 GMT
TestSync returnPen-Thu, 17 Oct 2019 09:38:53 GMT
测试不同线程执行不同对象上的同一方法
// 创建一个对象
SyncEntity syncEntity1 = new SyncEntity("TestSync1");
SyncEntity syncEntity2 = new SyncEntity("TestSync2");
// 创建一个线程池,这里用固定线程数量的
ExecutorService executorService = new ThreadPoolExecutor(2,2,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<>(), new ThreadFactoryBuilder().setNameFormat("自定义线程名称-%d").build());
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName()+" 开始执行。。。");
syncEntity1.getBook();
});
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName()+" 开始执行。。。");
syncEntity2.getBook();
});
// 关闭线程池
executorService.shutdown();
执行结果
自定义线程名称-1 开始执行。。。
自定义线程名称-0 开始执行。。。
TestSync1 getBook-Thu, 17 Oct 2019 09:43:41 GMT
TestSync2 getBook-Thu, 17 Oct 2019 09:43:41 GMT
TestSync2 returnBook-Thu, 17 Oct 2019 09:43:46 GMT
TestSync1 returnBook-Thu, 17 Oct 2019 09:43:46 GMT
结论:同步方法锁定当前对象
测试不同线程执行不同对象上的同一方法
// 创建一个线程池,这里用固定线程数量的
ExecutorService executorService = new ThreadPoolExecutor(2,2,0L, TimeUnit.MILLISECONDS,new LinkedBlockingQueue<>(), new ThreadFactoryBuilder().setNameFormat("自定义线程名称-%d").build());
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName()+" 开始执行。。。");
SyncEntity.getStaticCar("小汽车");
});
executorService.execute(() -> {
System.out.println(Thread.currentThread().getName()+" 开始执行。。。");
SyncEntity.getStaticBus("公交车");
});
// 关闭线程池
executorService.shutdown();
执行结果
自定义线程名称-0 开始执行。。。
自定义线程名称-1 开始执行。。。
公交车 getStaticBus-Thu, 17 Oct 2019 09:49:53 GMT
公交车 returnStaticBus-Thu, 17 Oct 2019 09:49:58 GMT
小汽车 getStaticCar-Thu, 17 Oct 2019 09:49:58 GMT
小汽车 returnStaticCar-Thu, 17 Oct 2019 09:50:03 GMT