《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)是计算机中的程序 ...
随机推荐
- GS踢玩家下线功能
GS踢玩家下线功能 //key:userId, val:nChannelId (当前在线用户) std::map<int, int> m_mapOnLineUserByUid; ///&l ...
- Oracle中日期和时间类函数
首先,在oracle中如何表示日期 操作日期时,应使用to_date('date','dateType')函数得到date类型,其中date为任意格式的日期,dateType指定其格式,如to_dat ...
- Arcgis SOE学习
http://blog.csdn.net/lovecarpenter/article/details/53178233 http://blog.csdn.net/lovecarpenter/artic ...
- 用JAVA 的for循环输出 菱形
public class For{ public static void main(String[] args){ //首先.把菱形看成上下两部分,上五下四,所以,第一个for循环有5次,第二个for ...
- NPM 与 Nodejs
安装了Nodejs之后,NPM也安装好了 如何知道当前是否已经安装Nodejs和NPM了呢? node -v //查看当前nodejs的版本 npm -v //查看当前npm的版本 NPM 初始化 n ...
- uboot移植添加nfs支持
手头6410开发板uboot(基于2011.06)其他功能包括ping和tftp都执行正常,唯独缺少nfs. 只需要在其配置文件(每个开发板文件通常名称不同,include/configs/*6410 ...
- iOS数据持久化存储之属性列表
属性列表(plist) iOS提供了一种plist格式的文件(属性列表)用于存储轻量级的数据,属性列表是一种XML格式的文件,拓展名为plist.如果对象是NSString.NSDictionary. ...
- 基于KD-Tree的最近邻搜索
目标:查询目标点附近的10个最近邻邻居. load fisheriris x = meas(:,:); figure(); g1=gscatter(x(:,),x(:,),species); %spe ...
- hdmap相关单词
交叉口(junction) 交叉口组(junctiongroup)
- css3立体旋转菜单
css3立体旋转菜单,css3,3D,立体旋转,立体菜单,菜单导航,css3立体旋转菜单是一款纯css3实现的三维立体旋转导航菜单. 源码下载页:http://www.huiyi8.com/sc/71 ...