26.

下面介绍synchronized代码块,个人以为,重要度远远高于单纯的修饰synchronized方法:

一方面:高效率!

另一方面:后面涉及到的wait和notify方法,都要涉及

Synchronized要修饰一个对象

即:synchronized(Object);

表示将对象object上锁,这里的object对象其实是没有用的,只是说明被上锁,个人建议使用this关键字,表示将当前对象上锁!

看下面的synchronized代码块代码同样实现了两个方法的顺序执行:

package thread;

public class BlockTest

{

public static void main(String[] args)

{

Block block = new Block();

ThreadTestX test1 = new ThreadTestX(block);

ThreadTestXX test2 = new ThreadTestXX(block);

test1.start();

test2.start();

}

}

class Block

{

public void method1()

{

synchronized (this)

{

for(int i = 0; i < 15; i++)

{

System.out.println("hello :"+ i);

}

}

}

public void method2()

{

synchronized(this)

{

for(int i = 0 ; i <15; i ++)

{

System.out.println("world!"+ i);

}

}

}

}

class ThreadTestXextends Thread

{

private Blockblock;

public ThreadTestX(Block block)

{

this.block = block;

}

@Override

public void run()

{

block.method1();

}

}

class ThreadTestXXextends Thread

{

private Blockblock;

public ThreadTestXX(Block block)

{

this.block = block;

}

@Override

public void run()

{

block.method2();

}

}

27.

Deadlock:

所谓死锁<DeadLock>:是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统产生了死锁,这些永远在互相等待的进程称为死锁进程.

产生deadlock的四个必要条件:

  (1) 互斥条件:一个资源每次只能被一个进程使用。

  (2) 请求与保持条件:一个进程因请求资源而阻塞时,对已获得的资源保持不放。

  (3) 不剥夺条件:进程已获得的资源,在末使用完之前,不能强行剥夺。

  (4) 循环等待条件:若干进程之间形成一种头尾相接的循环等待资源关系。

  这四个条件是死锁的必要条件,只要系统发生死锁,这些条件必然成立,而只要上述条件之

  一不满足,就不会发生死锁。

28.

一个线程就是一个类!

29.

Object类中的wait 、和 notify方法是用来处理线程的方法,既然定义在Object类中,两个方法的重要程度可见一斑:

两个方法的使用上都很复杂:通过阅读API获得更多对方法的理解:

The current thread must own this object'smonitor. The thread releases ownership of this monitor and waits until anotherthread notifies threads waiting on this object's monitor to wake up eitherthrough a call to thenotify method or the notifyAll method. The thread then waits until it can re-obtain ownership ofthe monitor and resumes execution

“当前的线程必须要获得对象的锁!”

实现这个条件的做法就是wait 方法一定要定义在synchronized方法中或者synchronized代码块中;

线程必须要两次获得锁才能完全的执行synchronized中的所有内容;

当第一次调用到达wait方法时,The thread realeases ownership of this monitor and waituntil another thread notifies threads waiting on this …

线程会暂时释放锁的拥有权,等待其他线程的notify方法或者notifyAll方法唤醒该线程,继续执行代码!

30.

下面一个程序要求定义两个线程类,一个实现将目标加一,一个实现将目标减一,目标初始值为零,要求加一减一交替进行;

显然的单纯调用synchronized是无法满足条件的,需要使用wait,和notify方法;

package thread;

public class ThreadTest

{

public static void main(String[] args)

{

ThreadDemo2 demo = new ThreadDemo2();

ThreadIncrease test1 = new ThreadIncrease(demo);

ThreadDecrease test2 = new ThreadDecrease(demo);

test1.start();

test2.start();

}

}

class ThreadDemo2

{

private int num = 0;

public synchronized void Increase()

{

/*

* 下面的代码是核心代码

* 什么时候要让线程等待,当然是不符合条件的时候

* 目的是想让num = 0的时候才执行加一的操作,当num不等于零的时候会执行wait等待通知

* 当通知num已经变为0时,wait结束,执行下面语句num++;

* 然后执行notify方法!

* 当然的一说Java中的synchronized总是伴随着wait和notify方法共同的存在;

*/

if(num != 0)

{

try

{

wait();

}

catch (InterruptedException e)

{

// TODO Auto-generatedcatch block

e.printStackTrace();

}

}

num ++;

System.out.println(num);

notify();

}

public synchronized void decrease()

{

if(num == 0)

{

try

{

wait();

}

catch (InterruptedException e)

{

// TODO Auto-generatedcatch block

e.printStackTrace();

}

}

num --;

System.out.println(num);

notify();

}

}

class ThreadIncreaseextends Thread

{

private ThreadDemo2demo;

public ThreadIncrease(ThreadDemo2 demo)

{

this.demo = demo;

}

@Override

public void run()

{

for(int i = 0 ; i < 15; i ++)

{

demo.Increase();

}

}

}

class ThreadDecreaseextends Thread

{

private ThreadDemo2demo;

public ThreadDecrease(ThreadDemo2 demo)

{

this.demo = demo;

}

@Override

public void run()

{

for(int i = 0 ; i < 15; i ++)

{

demo.decrease();

}

}

}

31.

可惜的是上面的代码仍然有着致命的弱点,线程并不仅仅有两个,而且是两个相对的线程!

致命的弱点在于: 当线程在wait的时候它并不知道其他的线程到底做了什么!

现在我们将增加一个Increase线程类,和一个Decrease线程类

,并且调用它们的start方法运行后,你将看到这样的结果:

我们足以看到代码的脆弱性,为什么会出现这种情况,更糟糕的是结果是随机的!上面已经说得很清楚了:当线程在wait的时候,它不知道其他的线程正在做什么,

所以需要将代码变得更加健壮:

我们举一个为什么会出现这种情况的原因之一:

我们假设线程1、2调用增加方法,线程3、4调用减少方法

假设线程3 先访问了减少方法,因为此时num的值为0,所以wait,并且交出ownership,假设线程4又访问了减少方法,同样的wait,并且交出所有权,再假设线程1访问了增加方法,将num的值变为1,并且调用notify方法,假设notify了线程3,线程3将num的值变为0;并且notify,如果此时notify了线程4,那么悲剧就会发生了,线程4醒来后,会继续将num减一,变为-1,一步错,后面就全错了;

缺点就在于notify的随机性,所以在某个wait方法被唤醒时,增加判断条件,如果不符合条件,继续wait,显然 while循环是最合适的

!

全部的变化只需要将 if 改为 while!!

由于num是成员变量被线程共享,每当wait被唤醒,都会判断一次;

package thread;

public class ThreadTest

{

public static void main(String[] args)

{

ThreadDemo2 demo = new ThreadDemo2();

ThreadIncrease test1 = new ThreadIncrease(demo);

ThreadDecrease test2 = new ThreadDecrease(demo);

ThreadIncrease test3 = new ThreadIncrease(demo);

ThreadDecrease test4 = new ThreadDecrease(demo);

test1.start();

test2.start();

test3.start();

test4.start();

}

}

class ThreadDemo2

{

private int num = 0;

public synchronized void Increase()

{

/*

* 下面的代码是核心代码

* 什么时候要让线程等待,当然是不符合条件的时候

* 目的是想让num = 0的时候才执行加一的操作,当num不等于零的时候会执行wait等待通知

* 当通知num已经变为0时,wait结束,执行下面语句num++;

* 然后执行notify方法!

* 当然的一说Java中的synchronized总是伴随着wait和notify方法共同的存在;

*/

while(num != 0)

{

try

{

wait();

}

catch (InterruptedException e)

{

// TODO Auto-generatedcatch block

e.printStackTrace();

}

}

num ++;

System.out.println(num);

notify();

}

public synchronized void decrease()

{

while(num == 0)

{

try

{

wait();

}

catch (InterruptedException e)

{

// TODO Auto-generatedcatch block

e.printStackTrace();

}

}

num --;

System.out.println(num);

notify();

}

}

class ThreadIncreaseextends Thread

{

private ThreadDemo2demo;

public ThreadIncrease(ThreadDemo2 demo)

{

this.demo = demo;

}

@Override

public void run()

{

for(int i = 0 ; i < 15; i ++)

{

try

{

Thread.sleep((long)(Math.random()*1000));

}

catch (InterruptedException e)

{

// TODO Auto-generatedcatch block

e.printStackTrace();

}

demo.Increase();

}

}

}

class ThreadDecreaseextends Thread

{

private ThreadDemo2demo;

public ThreadDecrease(ThreadDemo2 demo)

{

this.demo = demo;

}

@Override

public void run()

{

for(int i = 0 ; i < 15; i ++)

{

try

{

Thread.sleep((long)(Math.random()*1000));

}

catch (InterruptedException e)

{

// TODO Auto-generatedcatch block

e.printStackTrace();

}

demo.decrease();

}

}

}

32.

Object 中最后一个方法—— colone;

首先介绍浅克隆,被克隆的类必须实现了Cloneable接口

该接口是一个标识接口!

克隆的只是对象!

对于任何的拷贝对象X;一定有

1. X.clone() != X;

即克隆的对象与原对象肯定不是一个对象;

1.X.clone().getClass() ==x.getClass();

一个类不管有多少个对象,它们都有着共同的一个类!

2.如果设计的合适的话

x.clone().equals(x)是正确的;

下面是浅克隆:

package com.jianjian.clone;

public class CloneTest1

{

public static void main(String[] args)throws CloneNotSupportedException

{

Person person = new Person();

person.setAge(20);

person.setName("yangmanman");

Person person1 = (Person)person.clone();//注意到返回的对象是Object类型的,不要忘记类型转换;

System.out.println(person1.getAge());

System.out.println(person1.getName());

System.out.println(person1 == person);

System.out.println(person1.getClass() == person.getClass());

System.out.println(person1.equals(person));//我重写了equals方法;将结果返回true

}

}

class Person implements Cloneable

{

private int age;

private Stringname;

public int getAge()

{

return age;

}

public void setAge(int age)

{

this.age = age;

}

public String getName()

{

return name;

}

public void setName(String name)

{

this.name = name;

}

@Override//需要重写clone方法;

protected Object clone()throws CloneNotSupportedException

{

Object object = super.clone();

return object;

}

@Override

public int hashCode()

{

final int prime = 31;

int result = 1;

result = prime * result + age;

result = prime * result + ((name ==null) ? 0 :name.hashCode());

return result;

}

@Override

public boolean equals(Object obj)

{

if (this == obj)

return true;

if (obj ==null)

return false;

if (getClass() != obj.getClass())

return false;

Person other = (Person) obj;

if (age != other.age)

return false;

if (name ==null)

{

if (other.name !=null)

return false;

}

else if (!name.equals(other.name))

return false;

return true;

}

}

33.

关于深克隆,以后深究

Java学习笔记十五相关推荐

  1. python复制指定字符串_python3.4学习笔记(十五) 字符串操作(string替换、删除、截取、复制、连接、比较、查找、包含、大小写转换、分割等)...

    python3.4学习笔记(十五) 字符串操作(string替换.删除.截取.复制.连接.比较.查找.包含.大小写转换.分割等) python print 不换行(在后面加上,end=''),prin ...

  2. windows内核开发学习笔记十五:IRP结构

    windows内核开发学习笔记十五:IRP结构   IRP(I/O Request Package)在windows内核中,有一种系统组件--IRP,即输入输出请求包.当上层应用程序需要访问底层输入输 ...

  3. java学习记录十五:集合二Collections、Set、Map

    java学习记录十五:集合二 一.Collections工具类 一.解释 二.常用方法 1.打乱集合顺序 2.按照默认规则排序 3.按指定规则排序 4.批量添加元素 二.可变参数 一.解释 二.写法 ...

  4. Polyworks脚本开发学习笔记(十五)-用Python连接Polyworks的COM组件

    Polyworks脚本开发学习笔记(十五)-用Python连接Polyworks的COM组件 用Polyworks脚本开发,没有高级语言的支持,功能难免单一,一些比较复杂的交互实现不了,界面和报告也很 ...

  5. Java学习 第十五天

    Java学习 第十五天 第一章 StringBuilder类 1.1 字符串的不可变 1.2 StringBuilder概述 1.3 构造方法 1.4 两个常用方法 1.4.1 append方法 1. ...

  6. IOS之学习笔记十五(协议和委托的使用)

    1.协议和委托的使用 1).协议可以看下我的这篇博客 IOS之学习笔记十四(协议的定义和实现) https://blog.csdn.net/u011068702/article/details/809 ...

  7. Mr.J-- jQuery学习笔记(十五)--实现页面的对联广告

    请看之前的:Mr.J-- jQuery学习笔记(十四)--动画显示隐藏 话不多说,直接上demo <!DOCTYPE html> <html lang="en"& ...

  8. 世界是有生命的(通向财富自由之路学习笔记十五)

    最近因为工作调度的事情,有了一段空闲的日子,有比较多的时间来回望自己走过的路以及如何走好以后的路.之前忙得很少时间来写博文,很少时间来写读书笔记,逐渐将自己一些很好的习惯丢弃了.从今天起将重拾写博文的 ...

  9. Java学习 第十五章 成员变量和局部变量的区别 / 三大特征之一 (封装性)/构造方法 /private关键字

    第十五章 局部变量和成员变量: 1.定义位置不一样 局部变量:在方法内部定义 成员变量:在方法的外部,直接写在类当中 2.作用范围不一样 局部变量:只能在方法当中使用 成员变量:整个类都可以使用 3. ...

最新文章

  1. 【Web】Rest API 验证授权如何做?
  2. 老生常谈:文字常量区的那点事
  3. C++primer笔记之关联容器
  4. Programming Pearls Essay 01
  5. 警告: deleting object of polymorphic class type which has non_virtual destructor
  6. 003_JavaScript实现
  7. asp.net session 如何知道是哪个浏览器客户端_微服务下的分布式session管理
  8. linux上查看gitlab日志,如何查看Gitlab的版本?
  9. 钉钉微应用怎么进入_钉钉微应用开发免登流程
  10. 路由器与交换机的工作原理
  11. mysql 赋给用户权限 grant all privileges on
  12. ubuntu14.04+eigen3安裝(亲测)
  13. 使用Docker运行oracle11g企业版和简单配置
  14. 模式窗口showModalDialog的用法总结
  15. 上一篇的改进!!!!!
  16. 读jQuery源码释疑笔记3
  17. 科研论文检索方法入门(计算机领域)
  18. android客户端设计,图文详解Android客户端界面设计教程
  19. J2SE J2EE J2ME名字的来历
  20. Opencv中视频播放与进度控制

热门文章

  1. deque,list,queue,priority_queue
  2. HDU1588(矩阵连乘求和)
  3. 安装和使用VCLSkin美肤插件
  4. 防外挂和防木马的通用解决方案
  5. PHP、Node、Ruby和Python应用,漏洞修复
  6. scrapy发送翻页请求
  7. 阿里规定代码中禁用static修饰SimpleDateFormat,为何?
  8. 你了解HTTPS工作原理吗?
  9. 给你一个能生成1到5随机数的函数,用它写一个函数生成1到7的随机数
  10. 下一代低延时直播CDN:HLS、RTMP 与UDP +WebRTC