《Java多线程编程核心技术》读后感(五)
2024-09-28 21:18:53
下面验证上面三条结论
验证第一条结论:
package Second; public class MyObject {
}
package Second; public class Service { public void testMethod1(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();
}
}
} }
package Second; public class ThreadA extends Thread { private Service service;
private MyObject object; public ThreadA(Service service, MyObject object) {
super();
this.service = service;
this.object = object;
} @Override
public void run() {
super.run();
service.testMethod1(object);
} }
package Second; public class ThreadB extends Thread {
private Service service;
private MyObject object; public ThreadB(Service service, MyObject object) {
super();
this.service = service;
this.object = object;
} @Override
public void run() {
super.run();
service.testMethod1(object);
} }
package Second; public class Run1_1 { public static void main(String[] args) {
Service service = new Service();
MyObject object = new MyObject(); ThreadA a = new ThreadA(service, object);
a.setName("a");
a.start(); ThreadB b = new ThreadB(service, object);
b.setName("b");
b.start();
} }
同步的原因是使用了同一个“对象监视器“”。如果使用不同的“”对象监视器“”会出现什么效果呢?见下面
package Second; public class Run1_2 { public static void main(String[] args) {
Service service = new Service();
MyObject object1 = new MyObject();
MyObject object2 = new MyObject(); ThreadA a = new ThreadA(service, object1);
a.setName("a");
a.start(); ThreadB b = new ThreadB(service, object2);
b.setName("b");
b.start();
} }
package Second; public class Run1_2 { public static void main(String[] args) {
Service service = new Service();
MyObject object1 = new MyObject();
MyObject object2 = new MyObject(); ThreadA a = new ThreadA(service, object1);
a.setName("a");
a.start(); ThreadB b = new ThreadB(service, object2);
b.setName("b");
b.start();
} }
验证第2个结论
package Second; public class MyObject {
synchronized public void speedPrintString() {
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());
}
}
package Second; public class Service { public void testMethod1(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();
}
}
} }
package Second; public class ThreadA extends Thread { private Service service;
private MyObject object; public ThreadA(Service service, MyObject object) {
super();
this.service = service;
this.object = object;
} @Override
public void run() {
super.run();
service.testMethod1(object);
} }
package Second; public class ThreadB extends Thread {
private MyObject object; public ThreadB(MyObject object) {
super();
this.object = object;
} @Override
public void run() {
super.run();
object.speedPrintString();
}
}
package Second; public class Run { public static void main(String[] args) throws InterruptedException {
Service service = new Service();
MyObject object = new MyObject(); ThreadA a = new ThreadA(service, object);
a.setName("a");
a.start(); Thread.sleep(100); ThreadB b = new ThreadB(object);
b.setName("b");
b.start();
} }
验证第3个结论
其他代码与第二个实验相同
package Second; public class MyObject {
public void speedPrintString() {
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());
}
}
}
静态同步synchronized方法与synchronized(class)代码块
是对当前的*.java文件对应的class类进行持锁
package Second; public class Service { synchronized public static void printA() {
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 void printB() {
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "进入printB");
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "离开printB");
} }
package Second; public class ThreadA extends Thread {
@Override
public void run() {
Service.printA();
} }
package Second; public class ThreadB extends Thread {
@Override
public void run() {
Service.printB();
}
}
package Second; public class Run { public static void main(String[] args) { ThreadA a = new ThreadA();
a.setName("A");
a.start(); ThreadB b = new ThreadB();
b.setName("B");
b.start(); } }
下面展示synchronized关键字加到非static静态方法上的锁
package Second; public class Service { synchronized public static void printA() {
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 void printB() {
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "进入printB");
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "离开printB");
} synchronized public void printC() {
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "进入printC");
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "离开printC");
} }
package Second; public class ThreadA extends Thread {
private Service service; public ThreadA(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.printA();
} }
package Second; public class ThreadB extends Thread {
private Service service; public ThreadB(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.printB();
}
}
package Second; public class ThreadC extends Thread { private Service service; public ThreadC(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.printC();
}
}
异步的原因是持有不同的锁,一个是对象锁,另外一个是class锁,而class锁可以对类的所有对象实例起作用,下面验证
package Second; public class Service { synchronized public static void printA() {
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 void printB() {
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "进入printB");
System.out.println("线程名称为:" + Thread.currentThread().getName() + "在"
+ System.currentTimeMillis() + "离开printB");
} }
package Second; public class ThreadA extends Thread {
private Service service; public ThreadA(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.printA();
}
}
package Second; public class ThreadB extends Thread {
private Service service; public ThreadB(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.printB();
}
}
package Second; public class Run { public static void main(String[] args) { Service service1 = new Service();
Service service2 = new Service(); ThreadA a = new ThreadA(service1);
a.setName("A");
a.start(); ThreadB b = new ThreadB(service2);
b.setName("B");
b.start(); } }
同步synchronized(class)代码块的作用其实和synchronized static方法的作用是一样的。下面测试
package Second; public class Service { public static void printA() {
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 void printB() {
synchronized (Service.class) {
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "进入printB");
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "离开printB");
}
}
}
package Second; public class ThreadA extends Thread {
private Service service; public ThreadA(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.printA();
}
}
package Second; public class ThreadB extends Thread {
private Service service; public ThreadB(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.printB();
}
}
package Second; public class Run { public static void main(String[] args) { Service service1 = new Service();
Service service2 = new Service(); ThreadA a = new ThreadA(service1);
a.setName("A");
a.start(); ThreadB b = new ThreadB(service2);
b.setName("B");
b.start(); } }
数据类型String的常量池特性
package Second; public class Service {
public static void print(String stringParam) {
try {
synchronized (stringParam) {
while (true) {
System.out.println(Thread.currentThread().getName());
Thread.sleep(1000);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package Second; public class ThreadA extends Thread {
private Service service;
public ThreadA(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.print("AA");
}
}
package Second; public class ThreadB extends Thread {
private Service service;
public ThreadB(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.print("AA");
}
}
package Second; public class Run { public static void main(String[] args) { Service service = new Service(); ThreadA a = new ThreadA(service);
a.setName("A");
a.start(); ThreadB b = new ThreadB(service);
b.setName("B");
b.start(); } }
出现这样的情况就是因为String的两个值都是AA,两个线程持有相同的锁,所以造成线程B不能执行。这就是String常量池所带来的问题。
因此在大多数情况下,同步synchronized代码块都不使用String作为锁对象,而改用其他的,比如new object()实例化一个object对象,但它并不放入缓存中。
package Second; public class Service {
public static void print(Object object) {
try {
synchronized (object) {
while (true) {
System.out.println(Thread.currentThread().getName());
Thread.sleep(1000);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
package Second; public class ThreadA extends Thread {
private Service service; public ThreadA(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.print(new Object());
}
}
package Second; public class ThreadB extends Thread {
private Service service; public ThreadB(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.print(new Object());
}
}
package Second; public class Run { public static void main(String[] args) { Service service = new Service(); ThreadA a = new ThreadA(service);
a.setName("A");
a.start(); ThreadB b = new ThreadB(service);
b.setName("B");
b.start(); } }
交替打印是因为持有的锁不是同一个
同步synchronized方法无限等待与解决
同步方法容易造成死循环
package Second; public class Service {
synchronized public void methodA() {
Object object1 = new Object(); System.out.println("methodA begin");
boolean isContinueRun = true;
while (isContinueRun) {
}
System.out.println("methodA end"); } synchronized public void methodB() {
Object object2 = new Object(); System.out.println("methodB begin");
System.out.println("methodB end"); }
}
package Second; public class ThreadA extends Thread { private Service service; public ThreadA(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.methodA();
} }
package Second; public class ThreadB extends Thread { private Service service; public ThreadB(Service service) {
super();
this.service = service;
} @Override
public void run() {
service.methodB();
} }
package Second; public class Run { public static void main(String[] args) {
Service service = new Service(); ThreadA athread = new ThreadA(service);
athread.start(); ThreadB bthread = new ThreadB(service);
bthread.start();
} }
线程B永远得不到运行的机会,锁死了
package Second; public class Service {
public void methodA() {
Object object1 = new Object();
synchronized (object1) {
System.out.println("methodA begin");
boolean isContinueRun = true;
while (isContinueRun) {
}
System.out.println("methodA end");
}
} public void methodB() {
Object object2 = new Object();
synchronized (object2) {
System.out.println("methodB begin");
System.out.println("methodB end");
}
}
}
最新文章
- 高性能PHP框架thinkphp5.0.0 Beta发布-为API开发而设计
- 【前端】event.target 和 event.currentTarget 的区别
- duxcms SQL Injection In /admin/module/loginMod.class.php
- ios xib 中的 size class
- WPF 的datagrid 列名中没有显示下划线是怎么回事?
- sqlserver字段类型详解
- 聚类算法:K-means 算法(k均值算法)
- css3中的BFC,IFC,GFC和FFC(转载)
- 【原】手写一个promise
- 如何用Python网络爬虫爬取网易云音乐歌曲
- 有道云笔记MarkDown 插入图片
- Solr 05 - Solr Web管理界面的基本使用
- 【Linux网络编程】TCP网络编程中connect()、listen()和accept()三者之间的关系
- [转]PHP时区/MySql时区/Linux时区
- CSS实现输入框宽度随内容自适应效果
- ZZW原创_imdpd导入时产生的错误
- HPUX and AIX SSH 互信
- springmvc接收数组类型参数
- MySQL数据库调优技巧
- MYSQL-重做系统恢复MYSQL过程