《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)是计算机中的程序 ...
随机推荐
- EasyNVR RTSP转RTMP-HLS流媒体服务器前端构建之:使用BootstrapPagination以分页形式展示数据信息
上一篇介绍通过接口来获取数据,本篇将介绍如何以分页形式展示出接口获取到的数据 获取到的数据往往会很多,为了追去页面的美观和方便用户的检索,需要进行分页的展示: EasyNVR可接如多通道,当我们的通道 ...
- 九度OJ 1145:Candy Sharing Game(分享蜡烛游戏) (模拟)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:248 解决:194 题目描述: A number of students sit in a circle facing their teac ...
- 九度OJ 1021:统计字符 (基础题)
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:5418 解决:3146 题目描述: 统计一个给定字符串中指定的字符出现的次数. 输入: 测试输入包含若干测试用例,每个测试用 ...
- Moving Computation is Cheaper than Moving Data
https://hadoop.apache.org/docs/r1.2.1/hdfs_design.html Introduction The Hadoop Distributed File Syst ...
- viewport详解
本文主要讲解viewpor相关知识. 参考资料&内容来源 博客园:https://www.cnblogs.com/zaoa/p/8630393.html 博客园:http://www.cnbl ...
- UVA 11077 - Find the Permutations(递推)
UVA 11077 - Find the Permutations option=com_onlinejudge&Itemid=8&page=show_problem&cate ...
- linux c编程:进程间通信
进程间的通信包括管道,共享内存,信号量通信,消息队列,套借口(socket)和全双工管道通信 首先来看下管道的用法:管道顾名思义,就如同下水道管道一样,当从管道一端流水到另一端的时候,水流的方向是单方 ...
- 郝健: Linux内存管理学习笔记-第1节课【转】
本文转载自:https://blog.csdn.net/juS3Ve/article/details/80035751 摘要 MMU与分页机制 内存区域(内存分ZONE) LinuxBuddy分配算法 ...
- SDUT OJ 河床
河床 Time Limit: 3000ms Memory limit: 65536K 有疑问?点这里^_^ 题目描述 地理学家们经常要对一段河流进行测量分析.他们从上游开始向下游方向等距离地选择 ...
- Spring Boot2.0之Admin-UI分布式微服务监控中心
前面https://www.cnblogs.com/toov5/p/9823353.html 说的很不好用哈哈 还需要json格式化 我们可以用Admin-UI 比较爽歪歪 原理: 将所有服务的监控 ...