《Java多线程编程核心技术》读后感(四)
将任意对象作为对象监视器
synchronized同步代码块还支持任意对象,使用格式为synchronized(非this对象)


package Second;
public class Service {
private String usernameParam;
private String passwordParam;
private String anyString = new String();
public void setUsernamePassword(String username, String password) {
try {
synchronized (anyString) {
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "进入同步块");
usernameParam = username;
Thread.sleep(3000);
passwordParam = password;
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "离开同步块");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
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.setUsernamePassword("a", "aa");
}
}
package Second;
public class ThreadB extends Thread {
private Service service;
public ThreadB(Service service) {
super();
this.service = service;
}
@Override
public void run() {
service.setUsernamePassword("b", "bb");
}
}
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();
}
}


package Second;
public class Service {
private String usernameParam;
private String passwordParam;
public void setUsernamePassword(String username, String password) {
try {
String anyString = new String();
synchronized (anyString) {
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "进入同步块");
usernameParam = username;
Thread.sleep(3000);
passwordParam = password;
System.out.println("线程名称为:" + Thread.currentThread().getName()
+ "在" + System.currentTimeMillis() + "离开同步块");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}


package Second;
public class Service {
private String anyString = new String();
public void a() {
try {
synchronized (anyString) {
System.out.println("a begin");
Thread.sleep(3000);
System.out.println("a end");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
synchronized public void b() {
System.out.println("b begin");
System.out.println("b end");
}
}
package Second;
public class ThreadA extends Thread {
private Service service;
public ThreadA(Service service) {
super();
this.service = service;
}
@Override
public void run() {
service.a();
}
}
package Second;
public class ThreadB extends Thread {
private Service service;
public ThreadB(Service service) {
super();
this.service = service;
}
@Override
public void run() {
service.b();
}
}
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();
}
}

由于对象监视器不同,所以运行结果就是异步的

下面验证多个线程调用同一个方法是随机的
package Second; import java.util.ArrayList;
import java.util.List; public class MyList { private List list = new ArrayList(); synchronized public void add(String username) {
System.out.println("ThreadName=" + Thread.currentThread().getName()
+ "执行了add方法!");
list.add(username);
System.out.println("ThreadName=" + Thread.currentThread().getName()
+ "退出了add方法!");
} synchronized public int getSize() {
System.out.println("ThreadName=" + Thread.currentThread().getName()
+ "执行了getSize方法!");
int sizeValue = list.size();
System.out.println("ThreadName=" + Thread.currentThread().getName()
+ "退出了getSize方法!");
return sizeValue;
} }
package Second;
public class MyThreadA extends Thread {
private MyList list;
public MyThreadA(MyList list) {
super();
this.list = list;
}
@Override
public void run() {
for (int i = 0; i < 100000; i++) {
list.add("threadA" + (i + 1));
}
}
}
package Second;
public class MyThreadB extends Thread {
private MyList list;
public MyThreadB(MyList list) {
super();
this.list = list;
}
@Override
public void run() {
for (int i = 0; i < 100000; i++) {
list.add("threadB" + (i + 1));
}
}
}
package Second;
public class Test {
public static void main(String[] args) {
MyList mylist = new MyList();
MyThreadA a = new MyThreadA(mylist);
a.setName("A");
a.start();
MyThreadB b = new MyThreadB(mylist);
b.setName("B");
b.start();
}
}


下面展示多线程出现脏读的情况
package Second; import java.util.ArrayList;
import java.util.List; public class MyOneList { private List list = new ArrayList(); synchronized public void add(String data) {
list.add(data);
}; synchronized public int getSize() {
return list.size();
}; }
package Second;
public class MyService {
public MyOneList addServiceMethod(MyOneList list, String data) {
try {
synchronized (list) {
if (list.getSize() < 1) {
Thread.sleep(2000);
list.add(data);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return list;
}
}
package Second;
public class MyThread1 extends Thread {
private MyOneList list;
public MyThread1(MyOneList list) {
super();
this.list = list;
}
@Override
public void run() {
MyService msRef = new MyService();
msRef.addServiceMethod(list, "A");
}
}
package Second;
public class MyThread2 extends Thread {
private MyOneList list;
public MyThread2(MyOneList list) {
super();
this.list = list;
}
@Override
public void run() {
MyService msRef = new MyService();
msRef.addServiceMethod(list, "B");
}
}
package Second;
public class Run {
public static void main(String[] args) throws InterruptedException {
MyOneList list = new MyOneList();
MyThread1 thread1 = new MyThread1(list);
thread1.setName("A");
thread1.start();
MyThread2 thread2 = new MyThread2(list);
thread2.setName("B");
thread2.start();
Thread.sleep(6000);
System.out.println("listSize=" + list.getSize());
}
}

"脏读"出现了。出现的原因是两个线程以异步的方式返回list参数的size()大小。解决办法是“”同步化
package Second;
public class MyService {
public MyOneList addServiceMethod(MyOneList list, String data) {
try {
synchronized (list) {
if (list.getSize() < 1) {
Thread.sleep(2000);
list.add(data);
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return list;
}
}

由于list参数对象在项目中是一份实例,是单例的,而且也正需要对list参数的getsize()方法做同步的调用,所以就对list参数进行同步处理
《Java多线程编程核心技术》读后感(四)的更多相关文章
- java多线程编程核心技术——第四章总结
第一节使用ReentrantLock类 1.1使用ReentrantLock实现同步:测试1 1.2使用ReentrantLock实现同步:测试2 1.3使用Condition实现等待/同步错误用法与 ...
- java多线程编程核心技术(四)--Lock的使用
1.jdk1.5中新增了ReentrantLock类,该类也可以实现synchronized线程之间同步互斥的效果. 2.jdk1.5中新增了Condition类.在Lock对象中可以创建多个Cond ...
- Java多线程编程核心技术(三)多线程通信
线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体.线程间的通信就是成为整体的必用方案之一,可以说,使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时 ...
- Java多线程编程核心技术(二)对象及变量的并发访问
本文主要介绍Java多线程中的同步,也就是如何在Java语言中写出线程安全的程序,如何在Java语言中解决非线程安全的相关问题.阅读本文应该着重掌握如下技术点: synchronized对象监视器为O ...
- Java多线程编程核心技术(一)Java多线程技能
1.进程和线程 一个程序就是一个进程,而一个程序中的多个任务则被称为线程. 进程是表示资源分配的基本单位,线程是进程中执行运算的最小单位,亦是调度运行的基本单位. 举个例子: 打开你的计算机上的任务管 ...
- 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)是计算机中的程序 ...
随机推荐
- ClassNotFoundException Log
Studio 运行时异常: Error:Execution failed for task ':app:compileDebugJavaWithJavac'.> Compilation fail ...
- .net 平台下的AI框架
Aforge.net之旅——开篇:从识别验证码开始 基于AForge.Net框架的扑克牌识别 人工神经网络入门(4) —— AFORGE.NET简介 .NET开源工程推荐(Accord,AForge, ...
- php总结4——数组的定义及函数、冒泡排序
4.1 数组的定义 数组:变量存储的有序序列. 索引数组:下标为数字的数组. $数组名称(下标) 下标从0开始的数字. 直接定义: $arr[0]=123; $arr[1]="chi ...
- 用于string对象中字符截取的几种函数总结——语法、参数意义及用途举例
1. charAt():返回指定位置的字符. 语法:stringObject.charAt(index) 参数意义:index 必需,指字符在字符串中的下标.需要注意的是,字符串中第一个字符的下标是 ...
- php依据地理坐标获取国家、省份、城市,及周边数据类
功能:当App获取到用户的地理坐标时,能够依据坐标知道用户当前在那个国家.省份.城市.及周边有什么数据. 原理:基于百度Geocoding API 实现.须要先注冊百度开发人员.然后申请百度AK(密钥 ...
- HttpWebRequest的timeout和ReadWriteTimeout(转载)
公司[1]一牛人看我的代码,说我设置的timeout有误,还应该设置ReadWriteTimeout.本人很不服,于是上网查看了相关说明. HttpWebRequest httpWebRequest ...
- mysql错误:[Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY clause and contains nonaggregated
今天迁移django数据库的时候,跑程序的时候出现这样的错误: [Err] 1055 - Expression #1 of ORDER BY clause is not in GROUP BY cla ...
- Swift 烧脑体操(四) - map 和 flatMap
前言 Swift 其实比 Objective-C 复杂很多,相对于出生于上世纪 80 年代的 Objective-C 来说,Swift 融入了大量新特性.这也使得我们学习掌握这门语言变得相对来说更加困 ...
- CSS那个背景图片的坐标怎么设置?怎么计算的?
background:url(images/hh.gif) no-repeat -10px 0;},作用是移动背景的位置. 背影图片的左上角相对当前元素左上角的坐标. 右为X轴正半轴, 下为Y轴正半轴 ...
- 【转】PHP生成器 (generator)和协程的实现
原文地址:https://phphub.org/topics/1430 1.一切从 Iterator 和 Generator 开始 为便于新入门开发者理解,本文一半篇幅是讲述迭代器接口(Iterato ...
