java线程间的通信。
java里面new一个新的线程的时候,java的虚拟机会向操作系统索取新的内存,也就是说java启动一个新的线程所占用的内存,并不属于jvm内存的一部分。这些启动了的新的线程会共享java的内存空间,当两个不同的线程同时使用了堆空间里面的同一个对象的时候,有可能会产生安全问题,也就是线程的同步问题。
笔者目前所掌握的情况,线程间的通信,就是通过他们共同访问的对象来实现的,也就是Object类存在3个方法。wait(),notify()和notifyAll()。
使用synchronized可以对方法或者代码块加锁,当线程运行到synchronized的代码块或者方法的时候,会获取synchronized所绑定的对象的锁,并且只有一个线程可以获得该锁,获得该锁的线程,可以做什么事情呢?1,放弃已经获得的锁,2,通知其他等待该锁的线程执行。通过wait()方法,可以使当前线程放弃所获得的锁,使用notify()方法,可以通知其他等待的线程获取该锁。
从使用的角度来说,wait(),notify()和notifyAll()一般都是跟synchronized配合使用的,这几个方法一般存在synchronized块里面。
下面使用一个例子来实验线程间的通信。
利用线程间的通信机制来在控制台上输出0101.。
package com.pip.Thread.communication;
public class NumberHolder {
private int number;
public synchronized void increase() throws InterruptedException{
while(0!=number){
wait();
}
number++;
System.out.println(number);
notify();
}
public synchronized void decrease() throws InterruptedException{
while(0==number){
wait();
}
number--;
System.out.println(number);
notify();
}
}
增加number的线程:
package com.pip.Thread.communication;
public class IncreaseThread extends Thread {
public NumberHolder holder;
public IncreaseThread(NumberHolder holder) {
this.holder = holder;
}
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i <= 20; i++) {
try {
holder.increase();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
减少number的线程:
package com.pip.Thread.communication;
public class DecreaseThread extends Thread {
public NumberHolder holder;
public DecreaseThread(NumberHolder holder) {
this.holder = holder;
}
@Override
public void run() {
// TODO Auto-generated method stub
for (int i = 0; i <= 20; i++) {
try {
holder.decrease();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
测试类:
package com.pip.Thread.communication;
public class ThreadTest {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
NumberHolder nh = new NumberHolder();
IncreaseThread it = new IncreaseThread(nh);
DecreaseThread dt = new DecreaseThread(nh);
it.start();
dt.start();
}
}
例子中it和dt两个线程同时访问了numberholder hn,这里值得注意的是虽然两个线程访问的是同一个对象里面的不同的方法,但是他们锁的是同一个对象,换句话说,只要一个线程执行了synchronized里面,其他线程无法访问该对象其他的加了synchronized 的方法。