synchronized测试1
写两个线程调用同一个方法,在其中分别做一个class和this的调用,看结果
1.xx.class
public class Test{ public static void main(String[] args) { System.out.println(new Date().toLocaleString()+";开始创建t1..."); Thread t1 = new Thread(new Runnable() { public void run() { new Test().test("t1"); } }); System.out.println(new Date().toLocaleString()+";开始执行t1..."); t1.start(); System.out.println(new Date().toLocaleString()+";开始创建t2..."); Thread t2 = new Thread(new Runnable() { public void run() { new Test().test("t2"); } }); System.out.println(new Date().toLocaleString()+";开始执行t2..."); t2.start(); } public void test(String n){ System.out.println(new Date().toLocaleString()+";"+n+"来了"); synchronized (Test.class) { System.out.println(new Date().toLocaleString()+";"+n+" 我在这里休眠5秒"); try { Thread.sleep(5*1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(new Date().toLocaleString()+";"+n+" 结束"); } }
打印
2015-10-19 13:56:46;开始创建t1... 2015-10-19 13:56:47;开始执行t1... 2015-10-19 13:56:47;开始创建t2... 2015-10-19 13:56:47;t1来了 2015-10-19 13:56:47;t1 我在这里休眠5秒 2015-10-19 13:56:47;开始执行t2... 2015-10-19 13:56:47;t2来了 2015-10-19 13:56:52;t2 我在这里休眠5秒 2015-10-19 13:56:52;t1 结束 2015-10-19 13:56:57;t2 结束
从打印的结果可以看出,使用class在执行到synchronized时会等待其他占用的线程执行玩才会继续执行
2.对比this
//将上面的案例中的synchronized (Test.class) { 修改成 synchronized (this) {
执行打印输出结果
2015-10-19 14:01:22;开始创建t1... 2015-10-19 14:01:22;开始执行t1... 2015-10-19 14:01:22;开始创建t2... 2015-10-19 14:01:22;t1来了 2015-10-19 14:01:22;开始执行t2... 2015-10-19 14:01:22;t1 我在这里休眠5秒 2015-10-19 14:01:22;t2来了 2015-10-19 14:01:22;t2 我在这里休眠5秒 2015-10-19 14:01:27;t1 结束 2015-10-19 14:01:27;t2 结束
可以看到,使用this执行线程时只会考虑到同一个线程中的同步问题,严格来说是无法达到真正意义上的线程同步
通过调用不同的方法再次测试
首先看使用class代码展示
public class Test{ public static void main(String[] args) { System.out.println(new Date().toLocaleString()+";开始创建t1..."); Thread t1 = new Thread(new Runnable() { public void run() { new Test().test("t1"); } }); System.out.println(new Date().toLocaleString()+";开始执行t1..."); t1.start(); System.out.println(new Date().toLocaleString()+";开始创建t2..."); Thread t2 = new Thread(new Runnable() { public void run() { new Test().test1("t2"); } }); System.out.println(new Date().toLocaleString()+";开始执行t2..."); t2.start(); } public void test(String n){ System.out.println(new Date().toLocaleString()+";"+n+"来了"); synchronized (Test.class) { System.out.println(new Date().toLocaleString()+";"+n+" 我在这里休眠5秒"); try { Thread.sleep(5*1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(new Date().toLocaleString()+";"+n+" 结束"); } public void test1(String n){ System.out.println(new Date().toLocaleString()+";"+n+"来了"); synchronized (Test.class) { System.out.println(new Date().toLocaleString()+";"+n+" 我在这里休眠5秒"); try { Thread.sleep(5*1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(new Date().toLocaleString()+";"+n+" 结束"); } }
执行打印结果
2015-10-19 14:04:58;开始创建t1... 2015-10-19 14:04:58;开始执行t1... 2015-10-19 14:04:58;开始创建t2... 2015-10-19 14:04:58;t1来了 2015-10-19 14:04:58;t1 我在这里休眠5秒 2015-10-19 14:04:58;开始执行t2... 2015-10-19 14:04:58;t2来了 2015-10-19 14:05:03;t2 我在这里休眠5秒 2015-10-19 14:05:03;t1 结束 2015-10-19 14:05:08;t2 结束
通过打印结果可以看到基本与同一个方法执行的结果相同
同样也做this的测试
//将上面的案例中的synchronized (Test.class) { 修改成 synchronized (this) {
打印结果
2015-10-19 14:08:22;开始创建t1... 2015-10-19 14:08:22;开始执行t1... 2015-10-19 14:08:22;开始创建t2... 2015-10-19 14:08:22;t1来了 2015-10-19 14:08:22;t1 我在这里休眠5秒 2015-10-19 14:08:22;开始执行t2... 2015-10-19 14:08:22;t2来了 2015-10-19 14:08:22;t2 我在这里休眠5秒 2015-10-19 14:08:27;t1 结束 2015-10-19 14:08:27;t2 结束
打印结果基本相同
所以得出:在使用线程同步时,处理特殊情况外基本应该使用class
测试static中的线程同步
public class Test{ public static void main(String[] args) { System.out.println(new Date().toLocaleString()+";开始创建t1..."); Thread t1 = new Thread(new Runnable() { public void run() { test("t1"); } }); System.out.println(new Date().toLocaleString()+";开始执行t1..."); t1.start(); System.out.println(new Date().toLocaleString()+";开始创建t2..."); Thread t2 = new Thread(new Runnable() { public void run() { test("t2"); } }); System.out.println(new Date().toLocaleString()+";开始执行t2..."); t2.start(); } public static void test(String n){ System.out.println(new Date().toLocaleString()+";"+n+"来了"); synchronized (Test.class) { System.out.println(new Date().toLocaleString()+";"+n+" 我在这里休眠5秒"); try { Thread.sleep(5*1000); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(new Date().toLocaleString()+";"+n+" 结束"); } }
打印
2015-10-19 14:10:22;开始创建t1... 2015-10-19 14:10:23;开始执行t1... 2015-10-19 14:10:23;开始创建t2... 2015-10-19 14:10:23;t1来了 2015-10-19 14:10:23;t1 我在这里休眠5秒 2015-10-19 14:10:23;开始执行t2... 2015-10-19 14:10:23;t2来了 2015-10-19 14:10:28;t2 我在这里休眠5秒 2015-10-19 14:10:28;t1 结束 2015-10-19 14:10:33;t2 结束
从结果中可以看出与class执行是一样的,不区分static。