总结:
本篇主要介绍内部类和多线程以及锁对象变化时候的情况
静态内部类和多线程:
package chapter2.innerTest2; import chapter2.innerTest2.OutClass.innerClass1; import chapter2.innerTest2.OutClass.innerClass2; /* 演示innerClass1的method1方法对innerClass2上锁,其他线程只能以同步的方式调用innerClass2中的静态同步方法 同步还是异步,就是判断线程进入时,对象监视器是什么,这个对象是否有锁,这个锁是否被其他线程持有(或者说该线程能否取得该对象锁) 从输出可以看出t1和t2是异步的,但是t1和t3是同步的 输出为: t2进入innerClass1 的method2方法 t1进入innerClass1 的method1方法 j=0 i=0 i=1 j=1 i=2 j=2 i=3 j=3 i=4 j=4 i=5 j=5 j=6 i=6 j=7 i=7 j=8 i=8 j=9 i=9 t2离开innerClass1 的method2方法 t1离开innerClass1 的method1方法 t3进入innerClass2 的method1方法 k=0 k=1 k=2 k=3 k=4 k=5 k=6 k=7 k=8 k=9 t3离开innerClass2 的method1方法 */ public class Run { public static void main(String[] args) { final innerClass1 inc1=new innerClass1(); final innerClass2 inc2=new innerClass2(); Thread t1=new Thread(new Runnable() { public void run() { inc1.method1(inc2); } }, "t1"); Thread t2=new Thread(new Runnable() { public void run() { inc1.method2(); } }, "t2"); Thread t3=new Thread(new Runnable() { public void run() { inc2.method1(); } },"t3"); t1.start(); t2.start(); t3.start(); } } package chapter2.innerTest2; public class OutClass { static class innerClass1 { public void method1(innerClass2 class2) { String threadName = Thread.currentThread().getName(); synchronized (class2) { System.out.println(threadName + "进入innerClass1 的method1方法"); for (int i = 0; i < 10; i++) { System.out.println("i=" + i); try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(threadName + "离开innerClass1 的method1方法"); } } public synchronized void method2() { String threadName = Thread.currentThread().getName(); System.out.println(threadName + "进入innerClass1 的method2方法"); for (int j = 0; j < 10; j++) { System.out.println("j=" + j); try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(threadName + "离开innerClass1 的method2方法"); } } static class innerClass2 { public synchronized void method1(){ String threadName = Thread.currentThread().getName(); System.out.println(threadName + "进入innerClass2 的method1方法"); for (int k = 0; k < 10; k++) { System.out.println("k=" + k); try { Thread.sleep(100); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } System.out.println(threadName + "离开innerClass2 的method1方法"); } } }
2,锁变化
在将任何数据类型作为同步锁时,需要注意的是,是否有多个线程同时持有锁对象,如果同时持有相同的锁对象,则这些线程之间就是同步的;如果分别获得锁对象,这些线程之间就是异步的.
以String作为锁
package chapter2.setNewStringTwoLock; public class MyService { private String lock = "123"; public void testMethod() { try { synchronized (lock) { System.out.println(Thread.currentThread().getName() + " beging time=" + System.currentTimeMillis()); lock = "456"; Thread.sleep(2000); System.out.println(Thread.currentThread().getName() + " end time=" + System.currentTimeMillis()); } } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } package chapter2.setNewStringTwoLock; /* * 演示锁对象变化的情况 * 注释掉main线程的sleep过程 * a,b线程同时请求lock锁,a先持有,b等待,a,b线程的锁为同一个,都是"123",所以是同步的 * 输出为: a beging time=1525543623392 a end time=1525543625393 b beging time=1525543625394 b end time=1525543627394 */ public class Run1 { public static void main(String[] args) throws InterruptedException { MyService ms =new MyService(); ThreadA ta=new ThreadA(ms); ThreadB tb=new ThreadB(ms); ta.setName("a"); tb.setName("b"); ta.start(); // Thread.sleep(50); tb.start(); } } package chapter2.setNewStringTwoLock; /* * 演示锁对象变化的情况 * a线程执行的时候,改变了lock的对象,b线程获取锁的时候,和a的锁不同,所以是异步的 * 输出为: * a beging time=1525543489477 b beging time=1525543489527 a end time=1525543491478 b end time=1525543491527 */ public class Run2 { public static void main(String[] args) throws InterruptedException { MyService ms =new MyService(); ThreadA ta=new ThreadA(ms); ThreadB tb=new ThreadB(ms); ta.setName("a"); tb.setName("b"); ta.start(); Thread.sleep(50); tb.start(); } } package chapter2.setNewStringTwoLock; public class ThreadA extends Thread { private MyService ms; public ThreadA(MyService ms) { super(); this.ms=ms; } @Override public void run() { super.run(); ms.testMethod(); } } package chapter2.setNewStringTwoLock; public class ThreadB extends Thread { private MyService ms; public ThreadB(MyService ms) { super(); this.ms=ms; } @Override public void run() { super.run(); ms.testMethod(); } }
锁对象的属性变化,还是同一个对象,就是同一个锁
package chapter2.setNewPropertiesLockOne; /* * 演示当锁对象的属性变化时,只要还是同一个对象,那么多线程间还是同步的, * 和String不同,如果String的值变化,String就是不同的对象, * 输出为: a end time=1525544321226 b end time=1525544324227 */ public class Run { public static void main(String[] args) { try { Service sv=new Service(); UserInfo uif=new UserInfo(); ThreadA ta=new ThreadA(sv, uif); ta.setName("a"); ta.start(); Thread.sleep(50); ThreadB tb=new ThreadB(sv, uif); tb.setName("b"); tb.start(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } package chapter2.setNewPropertiesLockOne; public class Service { public void serviceMethodA(UserInfo uif){ synchronized (uif) { try { System.out.println(Thread.currentThread().getName()); uif.setUsername("abcabcabc"); Thread.sleep(3000); System.out.println("end time="+System.currentTimeMillis()); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } } package chapter2.setNewPropertiesLockOne; public class ThreadA extends Thread { private Service sv; private UserInfo uif; public ThreadA(Service sv, UserInfo uif) { this.sv=sv; this.uif=uif; } @Override public void run() { super.run(); sv.serviceMethodA(uif); } } package chapter2.setNewPropertiesLockOne; public class ThreadB extends Thread { private Service sv; private UserInfo uif; public ThreadB(Service sv, UserInfo uif) { this.sv=sv; this.uif=uif; } @Override public void run() { super.run(); sv.serviceMethodA(uif); } } package chapter2.setNewPropertiesLockOne; public class UserInfo { private String username="a"; private String passwd="aa"; public UserInfo() { } public UserInfo(String un,String pwd){ username=un; passwd=pwd; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPasswd() { return passwd; } public void setPasswd(String passwd) { this.passwd = passwd; } }
参考:<java多线程编程核心技术>