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

下面验证上面三条结论
验证第一条结论:
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");
}
}
}

《Java多线程编程核心技术》读后感(五)的更多相关文章
- java多线程编程核心技术——第五章总结
定时器Timer的使用 1.1方法schedule(TimerTask task, Date time)的测试 1.2方法schedule(TimerTask task, Date firstTime ...
- Java多线程编程核心技术(三)多线程通信
线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体.线程间的通信就是成为整体的必用方案之一,可以说,使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时 ...
- Java多线程编程核心技术(二)对象及变量的并发访问
本文主要介绍Java多线程中的同步,也就是如何在Java语言中写出线程安全的程序,如何在Java语言中解决非线程安全的相关问题.阅读本文应该着重掌握如下技术点: synchronized对象监视器为O ...
- Java多线程编程核心技术(一)Java多线程技能
1.进程和线程 一个程序就是一个进程,而一个程序中的多个任务则被称为线程. 进程是表示资源分配的基本单位,线程是进程中执行运算的最小单位,亦是调度运行的基本单位. 举个例子: 打开你的计算机上的任务管 ...
- 《Java多线程编程核心技术》知识梳理
<Java多线程编程核心技术> @author ergwang https://www.cnblogs.com/ergwang/ 文章末尾附pdf和png下载链接 第1章 Java多线程技 ...
- Java多线程编程核心技术---学习分享
继承Thread类实现多线程 public class MyThread extends Thread { @Override public void run() { super.run(); Sys ...
- Java多线程编程核心技术---对象及变量的并发访问(二)
数据类型String的常量池特性 在JVM中具有String常量池缓存的功能. public class Service { public static void print(String str){ ...
- Java多线程编程核心技术
Java多线程编程核心技术 这本书有利于对Java多线程API的理解,但不容易从中总结规律. JDK文档 1. Thread类 部分源码: public class Thread implements ...
- 《Java多线程编程核心技术》推荐
写这篇博客主要是给猿友们推荐一本书<Java多线程编程核心技术>. 之所以要推荐它,主要因为这本书写得十分通俗易懂,以实例贯穿整本书,使得原本抽象的概念,理解起来不再抽象. 只要你有一点点 ...
- 《java多线程编程核心技术》(一)使用多线程
了解多线程 进程和多线程的概念和线程的优点: 提及多线程技术,不得不提及"进程"这个概念.百度百科对"进程"的解释如下: 进程(Process)是计算机中的程序 ...
随机推荐
- curl post 请求 es 数据 REST 批量删除
curl -d "keyword=牛" http://api.com/path/index curl模拟http发送get或post接口测试 - 一生守候 - 博客园 http ...
- github Merge method
About merge methods on GitHub - User Documentation https://help.github.com/articles/about-merge-meth ...
- Webpack探索【10】--- 懒加载详解
本文主要讲懒加载方面相关内容.
- SD 相关表
一.客户主数据基本数据放在KNA1里:公司代码放在KNB1里:销售视图放在KNVV里:合作伙伴放在KNVP里: 二.信用主数据KNKK里有信贷限额.应收总额.特别往来:S066里是未清订单值:S067 ...
- 20170326 ABAP调用外部webservice 问题
1.SE80 创建企业服务: 代理生成:出现错误 库处理程序中出现例外 错误的值:未知类型参考ns1:ArrayOfMLMatnrResource 尝试: 一.测试本地文件:---无效 1. 将网址链 ...
- TensorFlow运行时出现warning如何设置禁止打印方法
有时候运行TensorFlow时比较烦人,经常报一些warning或者版本更新了之类的一些警告,如下: 那么如何去掉或者说不显示这些东西呢,可以通过简单添加几行代码搞定,来看一下. 这样就不会报警告了 ...
- mysql 创建用户与授权
权限管理 我们都知道,最高权限管理者是 root 用户 , 它拥有着最高的权限操作,包括 : select(查询) ,update(修改) , delete(删除,有事没事都不要用这个,反正也不能给这 ...
- Java类的加载与生命周期
一.概要: 类的生命周期从类的 加载.连接.初始化 开始,到类的 卸载结束: 二.几个阶段: 加载:查找并加载类的二进制数据.(把类的.class文件的二进制数据读入内存,存放在运行时数据区的方法区: ...
- POJ1113 Wall —— 凸包
题目链接:https://vjudge.net/problem/POJ-1113 Wall Time Limit: 1000MS Memory Limit: 10000K Total Submis ...
- css中字体大小在不同浏览器兼容性问题
css中使用font-size设定字体大小,不同浏览器的字体height一样,但是width不同,比如在火狐和谷歌中,font-size:20px,字体的高度变为20px,但是谷歌的字体宽度比火狐长 ...