多线程的通信:
方法的执行在栈帧完成的。
package com.roocon.thread.ta6;
import com.roocon.thread.t5.Singleton2;
public class Demo {
private volatile int signal;
public void set (int value) {
this.signal = value;
}
public int get () {
return signal;
}
public static void main(String[] args) {
Demo d = new Demo();
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("修改状态的线程执行...");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
d.set(1);
System.out.println("状态值修改成功。。。");
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
// 等待signal为1开始执行,否则不能执行
while(d.get() != 1) {
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 当信号为1 的时候,执行代码
System.out.println("模拟代码的执行...");
}
}).start();
}
}
线程的等待。
// 等待signal为1开始执行,否则不能执行
while(d.get() != 1) {
try {
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
这里要休眠释放cpu资源。这个就是拿共有的变量去判断的。
这个不好控制等待的时间。
-----------
wait和notify在使用的时候一定在同步的代码块执行。就是synchronized。
为什么?https://www.cnblogs.com/xiohao/p/7118102.html
解释:当一个线程正在某一个对象的同步方法中运行时调用了这个对象的wait()方法,那么这个线程将释放该对象的独占锁并被放入这个对象的等待队列。注意,wait()方法强制当前线程释放对象锁。这意味着在调用某对象的wait()方法之前,当前线程必须已经获得该对象的锁。因此,线程必须在某个对象的同步方法或同步代码块中才能调用该对象的wait()方法。当某线程调用某对象的notify()或notifyAll()方法时,任意一个(对于notify())或者所有(对于notifyAll())在该对象的等待队列中的线程,将被转移到该对象的入口队列。接着这些队列(译者注:可能只有一个)将竞争该对象的锁,最终获得锁的线程继续执行。如果没有线程在该对象的等待队列中等待获得锁,那么notify()和notifyAll()将不起任何作用。在调用对象的notify()和notifyAll()方法之前,调用线程必须已经得到该对象的锁。因此,必须在某个对象的同步方法或同步代码块中才能调用该对象的notify()或notifyAll()方法。
不加d.notify的话是当前的Thread类的实例。
wait和notify的例子:
package com.roocon.thread.ta6;
import com.roocon.thread.t5.Singleton2;
public class Demo2 {
private volatile int signal;
public void set (int value) {
this.signal = value;
}
public int get () {
return signal;
}
public static void main(String[] args) {
Demo2 d = new Demo2();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (d) {
System.out.println("修改状态的线程执行...");
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
d.set(1);
System.out.println("状态值修改成功。。。");
d.notify();
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (d) {
// 等待signal为1开始执行,否则不能执行
while(d.get() != 1) {
try {
d.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
// 当信号为1 的时候,执行代码
System.out.println("模拟代码的执行...");
}
}
}).start();
}
}
上面的while不可以改为if,不是线程安全的。
if(d.get() != 1) {
try {
d.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
wait和notify写在了run方法里面,创建target1和target2
抽出run里面的方法。
package com.roocon.thread.ta6;
public class Target1 implements Runnable {
private Demo3 demo;
public Target1(Demo3 demo) {
this.demo = demo;
}
@Override
public void run() {
demo.set();
}
}
package com.roocon.thread.ta6;
public class Target2 implements Runnable {
private Demo3 demo;
public Target2(Demo3 demo) {
this.demo = demo;
}
@Override
public void run() {
demo.get();
}
}
Demo3
package com.roocon.thread.ta6;
import java.util.concurrent.TimeUnit;
public class Demo3 {
private volatile int signal;
public synchronized void set () {
signal = 1;
notifyAll(); // notify方法会随机叫醒一个处于wait状态的线程,这个锁的就是当前对象的实例,和自己最近的对象。
// notifyAll叫醒所有的处于wait线程,争夺到时间片的线程只有一个
System.out.println("叫醒线程叫醒之后休眠开始...");
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public synchronized int get () {
System.out.println(Thread.currentThread().getName() + " 方法执行了...");
if(signal != 1) {
try {
wait();
System.out.println("叫醒之后");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(Thread.currentThread().getName() + " 方法执行完毕...");
return signal;
}
public static void main(String[] args) {
Demo3 d = new Demo3();
Target1 t1 = new Target1(d);//不同的t调用的方法是不同的
Target2 t2 = new Target2(d);
new Thread(t2).start();
new Thread(t2).start();
new Thread(t2).start();
new Thread(t2).start();
try {
TimeUnit.SECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
new Thread(t1).start();
}
}
当只有get的时候四个方法都执行了。而不是只执行一个。
为什么?走到wait的时候synchronized已经被释放掉了。
调用notify会拿到锁。
时机:等synchronized被释放掉再拿到锁。
----------------------ta6----------------------