wait/notify的作用

wait()方法的作用是使当前执行代码的线程进行等待,wait()是Object类的方法,用来将当前线程置入预执行队列中,并且在wait()所在的代码处停止执行,直到接到通知或被中断为止。wait()调用前,必须获得该对象的对象级锁,即只能在同步方法或者同步代码块中调用wait()方法,否则会抛出IllegalMonitorStateException。当wait()执行后,当前线程释放锁

notify()方法的作用是用来通知那些可能等待该对象的对象锁的其他线程,如果有多个线程等待,则随机挑选出一个wait状态的线程,对其发出通知,并使它等待获取该对象的对象锁。notify()调用前,必须获得该对象的对象级锁,即只能在同步方法或者同步代码块中调用notify()方法,否则会抛出IllegalMonitorStateException。当notify()方法执行后,不会马上释放该对象的锁,呈wait状态的线程也并不能马上获得该对象锁,要等到执行notify()的线程将程序执行完,也就是退出synchronized代码块后,当前线程才会释放锁。

notifyAll()方法和notify()作用基本是一样的,一个是唤醒全部的wait线程,一个是唤醒其中一个wait线程。

经典案例生产者和消费者

public class MyStack {
private List<String> list = new ArrayList<>(); public synchronized void push() {
try {
while (list.size() == 1) {
System.out.println("push:"+Thread.currentThread().getName()+"呈wait状态");
this.wait();
}
list.add("anyString=" + Math.random());
this.notifyAll();
System.out.println("push=" + list.size());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} public synchronized String pop(){
String returnValue = "";
try {
while(list.size() == 0){
System.out.println("pop:"+Thread.currentThread().getName()+"呈wait状态");
this.wait();
}
returnValue = list.get(0);
list.remove(0);
this.notifyAll();
System.out.println("pop="+list.size());
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return returnValue;
}
} public class Product {
private MyStack myStack;
public Product(MyStack myStack) {
this.myStack = myStack;
} public void pushService(){
myStack.push();
}
} public class Customer {
private MyStack myStack;
public Customer(MyStack myStack) {
this.myStack = myStack;
} public void popService(){
myStack.pop();
}
} public class ThreadCustomer extends Thread { private Customer customer; public ThreadCustomer(Customer customer) {
this.customer = customer;
} @Override
public void run() {
while(true){
customer.popService();
}
}
} public class ThreadProduct extends Thread { private Product product; public ThreadProduct(Product product) {
this.product = product;
} @Override
public void run() {
while(true){
product.pushService();
}
}
} public class Test {
public static void main(String[] args) throws InterruptedException { MyStack myStack = new MyStack();
Product p = new Product(myStack);
Customer c = new Customer(myStack); ThreadProduct pThread = new ThreadProduct(p);
ThreadCustomer cThread = new ThreadCustomer(c);
pThread.start();
cThread.start(); }
}

join的作用

join()是Thread类的一个方法,它的作用是使所属的线程x对象正常的执行run方法中的任务,而使当前线程z进行无限期的阻塞,等待线程x销毁后再继续执行线程z后面的代码。

public class MyThread extends Thread{
@Override
public void run() {
try {
System.out.println(System.currentTimeMillis());
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
} public class Test {
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
myThread.start();
myThread.join();
System.out.println("在myThread执行完后输出:" + System.currentTimeMillis());
}
}

测试结果:

1516170164683
在myThread执行完后输出:1516170167686

join和synchronized的区别

从上面的例子可以看出,join方法具有线程排队运行的作用,有些类是同步的运行效果。join和synchronized的区别是:join在内部使用wait()方法进行等待,而synchronized是使用“对象监视器”原理做为同步

join(long)和sleep(long)的区别

由于join的内部是使用wait来实现的,所以它具有释放锁的特点,而sleep没有这一特点。

源码如下:

 public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0; if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
} if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}

最新文章

  1. HTML设计模式学习笔记
  2. Jquery AJAX ASP.NET IIS 跨域 超简单解决办法
  3. 整理iOS9适配
  4. 模板(Template)
  5. PHPWind 8.7中插件金币竞价插件的漏洞
  6. js遍历json数据
  7. Windows 服务入门指南
  8. sublime c++ builder
  9. vi / vim 删除以及其它命令
  10. Aandroid Error之 新导入工程报Unable to resolve target &#39;android-18&#39;和R cannot be resolved
  11. 用过滤器和装饰者设计模式(静态代理)解决getParameter乱码问题
  12. springMVC整合JAXB
  13. readelf -s 命令‘symbol’名字显示不全
  14. canvas绘制一定数目的圆(均分)
  15. 使用 cURL 度量 Web 站点的响应时间
  16. Nginx反向代理后,java获取客户端真实IP地址
  17. 设计模式之代理模式(Proxy)(2)
  18. switch_case注意事项
  19. Java二叉树的实现与特点
  20. uImage是什么

热门文章

  1. PHP 之转换excel表格中的经纬度
  2. PHP 之中文转为拼音
  3. 【转载】Linux下各文件夹的含义和用途
  4. CVPR 2017 Paper list
  5. react typescript 父组件调用子组件
  6. 不抛异常的swap函数
  7. 瑞芯微ROCK960 RK3399固件烧录总结
  8. Python 元组和列表
  9. git 的简单使用(5)
  10. 1 Ipython、Jupyter 入门