java线程编程核心技术_《Java多线程编程核心技术》读后感(五)

26941a8cf0739b8ef2f1993b3eedf0b5.png

下面验证上面三条结论

验证第一条结论:

packageSecond;public classMyObject {

}

packageSecond;public classService {public voidtestMethod1(MyObject object) {synchronized(object) {try{

System.out.println("testMethod1 ____getLock time="

+ System.currentTimeMillis() + " run ThreadName="

+Thread.currentThread().getName());

Thread.sleep(2000);

System.out.println("testMethod1 releaseLock time="

+ System.currentTimeMillis() + " run ThreadName="

+Thread.currentThread().getName());

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}

}

packageSecond;public class ThreadA extendsThread {privateService service;privateMyObject object;publicThreadA(Service service, MyObject object) {super();this.service =service;this.object =object;

}

@Overridepublic voidrun() {super.run();

service.testMethod1(object);

}

}

packageSecond;public class ThreadB extendsThread {privateService service;privateMyObject object;publicThreadB(Service service, MyObject object) {super();this.service =service;this.object =object;

}

@Overridepublic voidrun() {super.run();

service.testMethod1(object);

}

}

packageSecond;public classRun1_1 {public static voidmain(String[] args) {

Service service= newService();

MyObject object= newMyObject();

ThreadA a= newThreadA(service, object);

a.setName("a");

a.start();

ThreadB b= newThreadB(service, object);

b.setName("b");

b.start();

}

}

f3e603e8d6703c4d8e50720df1ebcb76.png

同步的原因是使用了同一个“对象监视器“”。如果使用不同的“”对象监视器“”会出现什么效果呢?见下面

packageSecond;public classRun1_2 {public static voidmain(String[] args) {

Service service= newService();

MyObject object1= newMyObject();

MyObject object2= newMyObject();

ThreadA a= newThreadA(service, object1);

a.setName("a");

a.start();

ThreadB b= newThreadB(service, object2);

b.setName("b");

b.start();

}

}

packageSecond;public classRun1_2 {public static voidmain(String[] args) {

Service service= newService();

MyObject object1= newMyObject();

MyObject object2= newMyObject();

ThreadA a= newThreadA(service, object1);

a.setName("a");

a.start();

ThreadB b= newThreadB(service, object2);

b.setName("b");

b.start();

}

}

0c7d97b7f414eb00bdbcec6f2ea20d0a.png

验证第2个结论

packageSecond;public classMyObject {synchronized public voidspeedPrintString() {

System.out.println("speedPrintString ____getLock time="

+ System.currentTimeMillis() + " run ThreadName="

+Thread.currentThread().getName());

System.out.println("-----------------");

System.out.println("speedPrintString releaseLock time="

+ System.currentTimeMillis() + " run ThreadName="

+Thread.currentThread().getName());

}

}

packageSecond;public classService {public voidtestMethod1(MyObject object) {synchronized(object) {try{

System.out.println("testMethod1 ____getLock time="

+ System.currentTimeMillis() + " run ThreadName="

+Thread.currentThread().getName());

Thread.sleep(5000);

System.out.println("testMethod1 releaseLock time="

+ System.currentTimeMillis() + " run ThreadName="

+Thread.currentThread().getName());

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}

}

packageSecond;public class ThreadA extendsThread {privateService service;privateMyObject object;publicThreadA(Service service, MyObject object) {super();this.service =service;this.object =object;

}

@Overridepublic voidrun() {super.run();

service.testMethod1(object);

}

}

packageSecond;public class ThreadB extendsThread {privateMyObject object;publicThreadB(MyObject object) {super();this.object =object;

}

@Overridepublic voidrun() {super.run();

object.speedPrintString();

}

}

packageSecond;public classRun {public static void main(String[] args) throwsInterruptedException {

Service service= newService();

MyObject object= newMyObject();

ThreadA a= newThreadA(service, object);

a.setName("a");

a.start();

Thread.sleep(100);

ThreadB b= newThreadB(object);

b.setName("b");

b.start();

}

}

3d332c729192b977deffb785d13c194d.png

验证第3个结论

其他代码与第二个实验相同

packageSecond;public classMyObject {public voidspeedPrintString() {synchronized (this) {

System.out.println("speedPrintString ____getLock time="

+ System.currentTimeMillis() + " run ThreadName="

+Thread.currentThread().getName());

System.out.println("-----------------");

System.out.println("speedPrintString releaseLock time="

+ System.currentTimeMillis() + " run ThreadName="

+Thread.currentThread().getName());

}

}

}

1272cd7302fbdea5ef6f7e5e7a4063ae.png

静态同步synchronized方法与synchronized(class)代码块

是对当前的*.java文件对应的class类进行持锁

packageSecond;public classService {synchronized public static voidprintA() {try{

System.out.println("线程名称为:" +Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "进入printA");

Thread.sleep(3000);

System.out.println("线程名称为:" +Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "离开printA");

}catch(InterruptedException e) {

e.printStackTrace();

}

}synchronized public static voidprintB() {

System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"

+ System.currentTimeMillis() + "进入printB");

System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"

+ System.currentTimeMillis() + "离开printB");

}

}

packageSecond;public class ThreadA extendsThread {

@Overridepublic voidrun() {

Service.printA();

}

}

packageSecond;public class ThreadB extendsThread {

@Overridepublic voidrun() {

Service.printB();

}

}

packageSecond;public classRun {public static voidmain(String[] args) {

ThreadA a= newThreadA();

a.setName("A");

a.start();

ThreadB b= newThreadB();

b.setName("B");

b.start();

}

}

40d9bdf4d37dd9b513b5b4cf620363da.png

下面展示synchronized关键字加到非static静态方法上的锁

packageSecond;public classService {synchronized public static voidprintA() {try{

System.out.println("线程名称为:" +Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "进入printA");

Thread.sleep(3000);

System.out.println("线程名称为:" +Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "离开printA");

}catch(InterruptedException e) {

e.printStackTrace();

}

}synchronized public static voidprintB() {

System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"

+ System.currentTimeMillis() + "进入printB");

System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"

+ System.currentTimeMillis() + "离开printB");

}synchronized public voidprintC() {

System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"

+ System.currentTimeMillis() + "进入printC");

System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"

+ System.currentTimeMillis() + "离开printC");

}

}

packageSecond;public class ThreadA extendsThread {privateService service;publicThreadA(Service service) {super();this.service =service;

}

@Overridepublic voidrun() {

service.printA();

}

}

packageSecond;public class ThreadB extendsThread {privateService service;publicThreadB(Service service) {super();this.service =service;

}

@Overridepublic voidrun() {

service.printB();

}

}

packageSecond;public class ThreadC extendsThread {privateService service;publicThreadC(Service service) {super();this.service =service;

}

@Overridepublic voidrun() {

service.printC();

}

}

813ae905240995ede59dff8354446414.png

异步的原因是持有不同的锁,一个是对象锁,另外一个是class锁,而class锁可以对类的所有对象实例起作用,下面验证

packageSecond;public classService {synchronized public static voidprintA() {try{

System.out.println("线程名称为:" +Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "进入printA");

Thread.sleep(3000);

System.out.println("线程名称为:" +Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "离开printA");

}catch(InterruptedException e) {

e.printStackTrace();

}

}synchronized public static voidprintB() {

System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"

+ System.currentTimeMillis() + "进入printB");

System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"

+ System.currentTimeMillis() + "离开printB");

}

}

packageSecond;public class ThreadA extendsThread {privateService service;publicThreadA(Service service) {super();this.service =service;

}

@Overridepublic voidrun() {

service.printA();

}

}

packageSecond;public class ThreadB extendsThread {privateService service;publicThreadB(Service service) {super();this.service =service;

}

@Overridepublic voidrun() {

service.printB();

}

}

packageSecond;public classRun {public static voidmain(String[] args) {

Service service1= newService();

Service service2= newService();

ThreadA a= newThreadA(service1);

a.setName("A");

a.start();

ThreadB b= newThreadB(service2);

b.setName("B");

b.start();

}

}

87cced2731d77e8255dc7d90d7076dbc.png

同步synchronized(class)代码块的作用其实和synchronized static方法的作用是一样的。下面测试

packageSecond;public classService {public static voidprintA() {synchronized (Service.class) {try{

System.out.println("线程名称为:" +Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "进入printA");

Thread.sleep(3000);

System.out.println("线程名称为:" +Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "离开printA");

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}public static voidprintB() {synchronized (Service.class) {

System.out.println("线程名称为:" +Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "进入printB");

System.out.println("线程名称为:" +Thread.currentThread().getName()+ "在" + System.currentTimeMillis() + "离开printB");

}

}

}

packageSecond;public class ThreadA extendsThread {privateService service;publicThreadA(Service service) {super();this.service =service;

}

@Overridepublic voidrun() {

service.printA();

}

}

packageSecond;public class ThreadB extendsThread {privateService service;publicThreadB(Service service) {super();this.service =service;

}

@Overridepublic voidrun() {

service.printB();

}

}

packageSecond;public classRun {public static voidmain(String[] args) {

Service service1= newService();

Service service2= newService();

ThreadA a= newThreadA(service1);

a.setName("A");

a.start();

ThreadB b= newThreadB(service2);

b.setName("B");

b.start();

}

}

542277613d14a3d301e36952dce05c9d.png

数据类型String的常量池特性

956451b03597e93ab178e25b27629a9d.png

packageSecond;public classService {public static voidprint(String stringParam) {try{synchronized(stringParam) {while (true) {

System.out.println(Thread.currentThread().getName());

Thread.sleep(1000);

}

}

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}

packageSecond;public class ThreadA extendsThread {privateService service;publicThreadA(Service service) {super();this.service =service;

}

@Overridepublic voidrun() {

service.print("AA");

}

}

packageSecond;public class ThreadB extendsThread {privateService service;publicThreadB(Service service) {super();this.service =service;

}

@Overridepublic voidrun() {

service.print("AA");

}

}

packageSecond;public classRun {public static voidmain(String[] args) {

Service service= newService();

ThreadA a= newThreadA(service);

a.setName("A");

a.start();

ThreadB b= newThreadB(service);

b.setName("B");

b.start();

}

}

1e26ecf5d4558551f5398a17b9a3f6b8.png

出现这样的情况就是因为String的两个值都是AA,两个线程持有相同的锁,所以造成线程B不能执行。这就是String常量池所带来的问题。

因此在大多数情况下,同步synchronized代码块都不使用String作为锁对象,而改用其他的,比如new object()实例化一个object对象,但它并不放入缓存中。

packageSecond;public classService {public static voidprint(Object object) {try{synchronized(object) {while (true) {

System.out.println(Thread.currentThread().getName());

Thread.sleep(1000);

}

}

}catch(InterruptedException e) {

e.printStackTrace();

}

}

}

packageSecond;public class ThreadA extendsThread {privateService service;publicThreadA(Service service) {super();this.service =service;

}

@Overridepublic voidrun() {

service.print(newObject());

}

}

packageSecond;public class ThreadB extendsThread {privateService service;publicThreadB(Service service) {super();this.service =service;

}

@Overridepublic voidrun() {

service.print(newObject());

}

}

packageSecond;public classRun {public static voidmain(String[] args) {

Service service= newService();

ThreadA a= newThreadA(service);

a.setName("A");

a.start();

ThreadB b= newThreadB(service);

b.setName("B");

b.start();

}

}

cceba4cb9c968e7769b4d7baeee93735.png

交替打印是因为持有的锁不是同一个

同步synchronized方法无限等待与解决

同步方法容易造成死循环

packageSecond;public classService {synchronized public voidmethodA() {

Object object1= newObject();

System.out.println("methodA begin");boolean isContinueRun = true;while(isContinueRun) {

}

System.out.println("methodA end");

}synchronized public voidmethodB() {

Object object2= newObject();

System.out.println("methodB begin");

System.out.println("methodB end");

}

}

packageSecond;public class ThreadA extendsThread {privateService service;publicThreadA(Service service) {super();this.service =service;

}

@Overridepublic voidrun() {

service.methodA();

}

}

packageSecond;public class ThreadB extendsThread {privateService service;publicThreadB(Service service) {super();this.service =service;

}

@Overridepublic voidrun() {

service.methodB();

}

}

packageSecond;public classRun {public static voidmain(String[] args) {

Service service= newService();

ThreadA athread= newThreadA(service);

athread.start();

ThreadB bthread= newThreadB(service);

bthread.start();

}

}

cd2e588c875e8f1035f85ccb2e1d64af.png

线程B永远得不到运行的机会,锁死了

packageSecond;public classService {public voidmethodA() {

Object object1= newObject();synchronized(object1) {

System.out.println("methodA begin");boolean isContinueRun = true;while(isContinueRun) {

}

System.out.println("methodA end");

}

}public voidmethodB() {

Object object2= newObject();synchronized(object2) {

System.out.println("methodB begin");

System.out.println("methodB end");

}

}

}

8ef120e0d9438fe38b491f4beed746ab.png

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值