一、线程交互的基础知识
void notify():唤醒在此对象监视器上等待的单个线程。
void notifyAll():唤醒在此对象监视器上等待的所有线程。
void wait():导致当前的线程等待,直到其他线程调用此对象的 notify()方法或 notifyAll()方法。

当然,wait()还有另外两个重载方法:
void wait(long timeout):导致当前的线程等待,直到其他线程调用此对象的 notify()方法或 notifyAll()方法,或者超过指定的时间量。
void wait(long timeout, int nanos):导致当前的线程等待,直到其他线程调用此对象的 notify()方法或 notifyAll()方法,或者其他某个线程中断当前线程,或者已超过某个实际时间量。

关于等待/通知,要记住的关键点是:
必须从同步代码块内调用wait()、notify()、notifyAll()方法。线程不能调用对象上等待或通知的方法,除非它拥有那个对象的锁。

wait()、notify()、notifyAll()都是Object的实例方法。与每个对象具有锁一样,每个对象可以有一个线程列表,他们等待来自该信号(通知)。线程通过执行对象上的wait()方法获得这个等待列表。从那时候起,它不再执行任何其他指令,直到调用对象的notify()方法为止。如果多个线程在同一个对象上等待,则将只选择一个线程(不保证以何种顺序)继续执行。如果没有线程等待,则不采取任何特殊操作。

例子

package cn.thread;

/**
* 计算1+2+3 ... +100的和
*
* @author 林计钦
* @version 1.0 2013-7-23 上午10:06:04
*/
public class ThreadSum extends Thread {
int total = 0; @Override
public void run() { synchronized (this) {
for (int i = 0; i < 101; i++) {
total += i;
}
//(完成计算了)唤醒在此对象监视器上等待的单个线程,在本例中线程ThreadInteractionTest被唤醒
notify();
} }
}
package cn.thread;

/**
* 线程的交互
*
* @author 林计钦
* @version 1.0 2013-7-23 上午10:04:11
*/
public class ThreadInteractionTest {
public static void main(String[] args) { ThreadSum sum = new ThreadSum();
// 启动计算线程
sum.start();
// 线程ThreadInteractionTest拥有sum对象上的锁。
// 线程为了调用wait()或notify()方法,该线程ThreadInteractionTest必须是那个对象锁的拥有者
synchronized (sum) {
try {
System.out.println("等待对象sum完成计算。。。");
// 当前线程ThreadInteractionTest等待
sum.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sum对象计算的总和是:" + sum.total);
} }
}
等待对象sum完成计算。。。
sum对象计算的总和是:5050

注意:当在对象上调用wait()方法时,执行该代码的线程立即放弃它在对象上的锁。然而调用notify()时,并不意味着这时线程会放弃其锁。如果线程仍然在完成同步代码,则线程在移出之前不会放弃锁。因此,只要调用notify()并不意味着这时该锁变得可用。

二、多个线程在等待一个对象锁时使用notifyAll()
在多数情况下,最好通知等待某个对象的所有线程。如果这样做,可以在对象上使用notifyAll()让所有在此对象上等待的线程冲出等待区,返回到可运行状态。

package cn.thread;

/**
* 计算1+2+3 ... +100的和
*
* @author 林计钦
* @version 1.0 2013-7-23 上午10:06:04
*/
public class ThreadSum2 extends Thread {
int total = 0; @Override
public void run() { synchronized (this) {
for (int i = 0; i < 101; i++) {
total += i;
}
//通知所有在此对象上等待的线程
notifyAll();
} }
}
package cn.thread;

/**
* 线程的交互
*
* @author 林计钦
* @version 1.0 2013-7-23 上午10:04:11
*/
public class ThreadInteractionTest2 extends Thread{
ThreadSum2 sum; public ThreadInteractionTest2(ThreadSum2 sum){
this.sum=sum;
} @Override
public void run() {
synchronized (sum) {
try {
System.out.println("等待对象sum完成计算。。。");
// 当前线程ThreadInteractionTest等待
sum.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("sum对象计算的总和是:" + sum.total);
}
} public static void main(String[] args) {
ThreadSum2 sum = new ThreadSum2(); //启动三个线程,分别获取计算结果
new ThreadInteractionTest2(sum).start();
new ThreadInteractionTest2(sum).start();
new ThreadInteractionTest2(sum).start(); // 启动计算线程
sum.start(); }
}
等待对象sum完成计算。。。
等待对象sum完成计算。。。
等待对象sum完成计算。。。
sum对象计算的总和是:5050
sum对象计算的总和是:5050
sum对象计算的总和是:5050

谈一下synchronized和wait()、notify()等的关系:
1、有synchronized的地方不一定有wait,notify
2、有wait,notify的地方必有synchronized.这是因为wait和notify不是属于线程类,而是每一个对象都具有的方法,而且,这两个方法都和对象锁有关,有锁的地方,必有synchronized。
另外,注意一点:如果要把notify和wait方法放在一起用的话,必须先调用notify后调用wait,因为如果调用完wait,该线程就已经不是currentthread了。

Java多线程-线程的交互的更多相关文章

  1. java 多线程—— 线程让步

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  2. java 多线程—— 线程等待与唤醒

    java 多线程 目录: Java 多线程——基础知识 Java 多线程 —— synchronized关键字 java 多线程——一个定时调度的例子 java 多线程——quartz 定时调度的例子 ...

  3. Java多线程--线程及相关的Java API

    Java多线程--线程及相关的Java API 线程与进程 进程是线程的容器,程序是指令.数据的组织形式,进程是程序的实体. 一个进程中可以容纳若干个线程,线程是轻量级的进程,是程序执行的最小单位.我 ...

  4. Java多线程-线程的同步(同步方法)

    线程的同步是保证多线程安全访问竞争资源的一种手段.线程的同步是Java多线程编程的难点,往往开发者搞不清楚什么是竞争资源.什么时候需要考虑同步,怎么同步等等问题,当然,这些问题没有很明确的答案,但有些 ...

  5. Java多线程——线程的优先级和生命周期

    Java多线程——线程的优先级和生命周期 摘要:本文主要介绍了线程的优先级以及线程有哪些生命周期. 部分内容来自以下博客: https://www.cnblogs.com/sunddenly/p/41 ...

  6. Java多线程——线程的创建方式

    Java多线程——线程的创建方式 摘要:本文主要学习了线程的创建方式,线程的常用属性和方法,以及线程的几个基本状态. 部分内容来自以下博客: https://www.cnblogs.com/dolph ...

  7. Java多线程——线程之间的协作

    Java多线程——线程之间的协作 摘要:本文主要学习多线程之间是如何协作的,以及如何使用wait()方法与notify()/notifyAll()方法. 部分内容来自以下博客: https://www ...

  8. Java多线程——线程的死锁

    Java多线程——线程的死锁 摘要:本文主要介绍了Java多线程中遇到的死锁问题. 部分内容来自以下博客: https://www.cnblogs.com/wy697495/p/9757982.htm ...

  9. Java多线程——线程之间的同步

    Java多线程——线程之间的同步 摘要:本文主要学习多线程之间是如何同步的,如何使用volatile关键字,如何使用synchronized修饰的同步代码块和同步方法解决线程安全问题. 部分内容来自以 ...

随机推荐

  1. 【数据库】python访问mysql

    import MySQLdb 所有的数据库遵循相同的python database API 需要建立connection对象连接数据库,之后建立cursor对象处理数据. conn = MySQLdb ...

  2. PostgreSQL 全文检索

    PostgreSQL 8.3.1  全文检索(转) 在postgreSQL 8.3自带支持全文检索功能,在之前的版本中需要安装配置tsearch2才能使用,安转配置tsearch2就不再多说了,主要介 ...

  3. GeoWebCache的配置与使用

    最近在做一个开源GIS的demo的工作,工作中涉及到了地图瓦片,选取的开发环境是geoserver+openlayers,那么地图瓦片自然而然也就使用geowebcache,geowebcache就相 ...

  4. 谈谈Java基础数据类型

    Java的基本数据类型 类型 意义 取值 boolean 布尔值 true或false byte 8位有符号整型 -128~127 short 16位有符号整型 -pow(2,15)~pow(2,15 ...

  5. Discuz代码研究-编码规范

    Discuz中的编码规范很值得PHP开发人员借鉴.里面既介绍了编码时代码标记,注释,书写规则,命名原则等方面基础的内容,对代码的安全性,性能,兼容性,代码重用,数据库设计,数据库性能及优化作了阐述,这 ...

  6. node.js之npm库

    npm库安装可分为本地安装和全局安装,本地安装如下: npm install <Module name> 但是好像会出问题,官方貌似推荐全局安装,so 全局安装官方所给命令如下: npm ...

  7. [python] 排序的动态展示

    两句闲话 本文所说的排序是指基于交换的排序.因此,按理来说,本文应该叫基于交换的排序的动态展示,但是这样太拗口了. 效果展示 最终效果如下. 实现方法 需要说明的是,在这里是通过pygame来实现图形 ...

  8. sizeof与strlen()、递归优化题解

    一.sizeof sizeof是C/C++中的一个操作符(operator),确切的说是一个编译时运算符,参数可以是数组.指针.类型.对象.函数等.用于统计类型或者变量所占的内存字节数.由于在编译时计 ...

  9. json数据格式字符串在java中的转移

    说明:项目中遇到请求的json数据字符串,打印出来没有问题,但是想加入到代码中,就需要进行转移 原数据为(用src代替)(没有写完): {"adjust_fee":"0. ...

  10. C#如何动态设置屏幕分辨率

    C#如何动态设置屏幕分辨率 作者:Learning hard 这篇文章主要为大家详细介绍了C#动态设置屏幕分辨率的方法,我们可以使用Screen类设置屏幕分辨率,感兴趣的小伙伴们可以参考一下 下面就不 ...