3.6 线程通信
线程通信是指不同线程之间相互传递信息。线程通信可以实现线程等待其他线程执行结果后再执行,这样来实现不同线程之间按照有序的方式进行工作。
那么问题来了,Java要如何实现线程间通信呢?
3.6.1 实现通信–共享变量
可以通过共享变量来实现,实现思路就是一个通过一个共享变量状态的改变来实现线程通信。下边就从代码来看下。
public class SignalDemo {
// private Object obj = new Object();
boolean singal = false;
public boolean isSingal() {
return singal;
}
public void setSingal(boolean singal) {
this.singal = singal;
}
public static void main(String[] args) {
SignalDemo signalDemo = new SignalDemo();
new Thread(()->{
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
signalDemo.setSingal(true);
System.err.println("\r\n线程2修改信号值");
}).start();
while (!signalDemo.isSingal()){
System.err.print("k");
}
}
}
上例实现的就是一个线程工作,然后另一个线程通过改变共享变量来终止工作线程,Just it!
3.6.2 wait-notify机制
官方注释:wait方法可以使当前线程进入等待直到其他线程调用了对象的notify或者notifyAll方法。该方法本质上调用的是wait(0).
* Causes the current thread to wait until another thread invokes the
* {@link java.lang.Object#notify()} method or the
* {@link java.lang.Object#notifyAll()} method for this object.
* In other words, this method behaves exactly as if it simply
* performs the call {@code wait(0)}.
现在了解了wait-notify的机制后看一个小demo。用两个线程一个线程输出0-100以内的奇数,一个线程输出0-100以内的偶数。
class SignalDemo2{
Object myMonitorObject = new Object();
public void doWait(){
synchronized(myMonitorObject){
try{
myMonitorObject.wait();
} catch(InterruptedException e){
e.printStackTrace();
}
}
}
public void doNotify(){
synchronized(myMonitorObject){
myMonitorObject.notify();
}
}
public static void main(String[] args) {
Object o = new Object();
AtomicInteger i= new AtomicInteger();
new Thread(()->{
synchronized (o){
while (i.get() <=100){
if (i.get() %2==0) {
System.err.println(Thread.currentThread() + ":" + i);
i.getAndIncrement();
try {
o.wait();
o.notify();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}).start();
new Thread(()->{
synchronized (o){
while (i.get() <=100){
if (i.get() %2!=0) {
System.err.println(Thread.currentThread() + ":" + i);
i.getAndIncrement();
try {
o.notify();
o.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}).start();
}
}
该实现原理非常简单,当一个线程输出奇数或者偶数后,就使当前线程进入等待状态,并且通知对方操作。 注意:当使用wait-notify机制的时候不要使用String对象或者全局变量的wait方法,可能会由于String常量引用导致意想不到的结果。