《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)是计算机中的程序 ...
随机推荐
- boost::noncopyable
/** * boost::noncopyable 实现单例不用麻烦了,直接从这个继承就行了 */ #include <boost/noncopyable.hpp> class myclas ...
- EasyPusher进行Android UVC外接摄像头直播推送实现方法
最近EasyPusher针对UVC摄像头做了适配.我们结合了UVCCamera与EasyPusher,支持将UVC摄像头的视频推送到RTSP服务器上.在此特别感谢UVCCamera这个牛逼的项目! 来 ...
- 在调用Response.End()时,会执行Thread.CurrentThread.Abort()操作
在调用Response.End()时,会执行Thread.CurrentThread.Abort()操作. 如果将Response.End()放在try...catch中,catch会捕捉Thread ...
- 箭头函数 this arrow function 无this
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions import w ...
- UVa 10828 Back to Kernighan-Ritchie 高斯消元+概率DP
题目来源:UVa 10828 Back to Kernighan-Ritchie 题意:从1開始 每次等概率从一个点到和他相邻的点 有向 走到不能走停止 求停止时每一个点的期望 思路:写出方程消元 方 ...
- php 生成bing词典能导入的xml(有道词典->bing词典)
编程以来一直用网易有道词典查单词.翻译:最近一直在看英文方面的资料,于是越来越对有道词典(划词.广告,本来想转灵格斯的,但灵格斯没有android版)不满意,一番试用后决定转bing词典,于是想把有道 ...
- 《高性能Javascript》 Summary(三)
第八章.编程实践 Programming Practices 经验: 避免使用 eval_r()和Function构造器避免二次评估.此外,给setTimeout()和setInterval()函数传 ...
- EASYARM-IMX283 制作ubifs文件系统
ubifs主页:http://www.linux-mtd.infradead.org/doc/ubifs.html nandflash上常用的文件系统有jffs2.yaffs和ubifs,其中ubif ...
- win下发现两个有用的快捷键
调出命令行工具:win+x然后a.默认是cmd的管理员模式,可以改成powershell. 从当前目录打开命令行:shift + 鼠标右键
- matlab的代码注释
1.注释一块代码: %{ 此处代码块 %} 2.注释数行代码: 先选中,然后用组合键Ctrl+R 取消注释,用组合键Ctrl+T 3.双%%的作用:代码分块运行,点击双%%之间的代码,再点Run Se ...
