将任意对象作为对象监视器

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多线程编程核心技术》读后感(四)的更多相关文章

  1. java多线程编程核心技术——第四章总结

    第一节使用ReentrantLock类 1.1使用ReentrantLock实现同步:测试1 1.2使用ReentrantLock实现同步:测试2 1.3使用Condition实现等待/同步错误用法与 ...

  2. java多线程编程核心技术(四)--Lock的使用

    1.jdk1.5中新增了ReentrantLock类,该类也可以实现synchronized线程之间同步互斥的效果. 2.jdk1.5中新增了Condition类.在Lock对象中可以创建多个Cond ...

  3. Java多线程编程核心技术(三)多线程通信

    线程是操作系统中独立的个体,但这些个体如果不经过特殊的处理就不能成为一个整体.线程间的通信就是成为整体的必用方案之一,可以说,使线程间进行通信后,系统之间的交互性会更强大,在大大提高CPU利用率的同时 ...

  4. Java多线程编程核心技术(二)对象及变量的并发访问

    本文主要介绍Java多线程中的同步,也就是如何在Java语言中写出线程安全的程序,如何在Java语言中解决非线程安全的相关问题.阅读本文应该着重掌握如下技术点: synchronized对象监视器为O ...

  5. Java多线程编程核心技术(一)Java多线程技能

    1.进程和线程 一个程序就是一个进程,而一个程序中的多个任务则被称为线程. 进程是表示资源分配的基本单位,线程是进程中执行运算的最小单位,亦是调度运行的基本单位. 举个例子: 打开你的计算机上的任务管 ...

  6. Java多线程编程核心技术---学习分享

    继承Thread类实现多线程 public class MyThread extends Thread { @Override public void run() { super.run(); Sys ...

  7. Java多线程编程核心技术---对象及变量的并发访问(二)

    数据类型String的常量池特性 在JVM中具有String常量池缓存的功能. public class Service { public static void print(String str){ ...

  8. Java多线程编程核心技术

    Java多线程编程核心技术 这本书有利于对Java多线程API的理解,但不容易从中总结规律. JDK文档 1. Thread类 部分源码: public class Thread implements ...

  9. 《Java多线程编程核心技术》推荐

    写这篇博客主要是给猿友们推荐一本书<Java多线程编程核心技术>. 之所以要推荐它,主要因为这本书写得十分通俗易懂,以实例贯穿整本书,使得原本抽象的概念,理解起来不再抽象. 只要你有一点点 ...

  10. 《java多线程编程核心技术》(一)使用多线程

    了解多线程 进程和多线程的概念和线程的优点: 提及多线程技术,不得不提及"进程"这个概念.百度百科对"进程"的解释如下: 进程(Process)是计算机中的程序 ...

随机推荐

  1. IOS开发之----异常处理

    本文转载至 http://blog.csdn.net/chenyong05314/article/details/7906593 转载自:http://blog.sina.com.cn/s/blog_ ...

  2. 【BZOJ4942】[Noi2017]整数 线段树+DFS(卡过)

    [BZOJ4942][Noi2017]整数 题目描述去uoj 题解:如果只有加法,那么直接暴力即可...(因为1的数量最多nlogn个) 先考虑加法,比较显然的做法就是将A二进制分解成log位,然后依 ...

  3. JavaScript中实现继承

    今天即兴研究了下JS,查阅了相关资料 ,发现Js中没有"子类"和"父类"的概念,也没有"类"(class)和"实例"(i ...

  4. Django框架创建数据库表时setting文件配置_模型层

    若想将模型转为mysql数据库中的表,需要在settings中配置: 一. 确保配置文件中的INSTALLED_APPS中写入我们创建的app名称-->bms INSTALLED_APPS = ...

  5. 【Android】Android中AlertDialog对话框的使用实例

    package com.ceac.deng; import android.R.string; import android.support.v7.app.ActionBarActivity; imp ...

  6. 程序连接Oracle数据库出现未找到提供程序.该程序可能未正确安装错误提示

    好不容易使用plsql可以成功连上数据库了,应用程序连接数据库却出现了问题 其实解决这个问题也简单: 1.  查看oracle安装目录下的BIN目录,E:\app\Administrator\prod ...

  7. BZOJ 1607 [Usaco2008 Dec]Patting Heads 轻拍牛头:统计 + 筛法【调和级数】

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1607 题意: 给你n个数,问你除a[i]之外,有多少个数是a[i]的约数. 题解: ans ...

  8. CentOS Wifi Connection

    方法一: http://wiki.centos.org/HowTos/Laptops/WpaSupplicant http://www.cnblogs.com/tanghuimin0713/p/343 ...

  9. (转)RTSP协议详解

    转自:https://www.cnblogs.com/lidabo/p/6553212.html RTSP简介     RTSP(Real Time Streaming Protocol)是由Real ...

  10. codeforces 659B B. Qualifying Contest(水题+sort)

    题目链接: B. Qualifying Contest time limit per test 1 second memory limit per test 256 megabytes input s ...