学习笔记之线程间通信

来源:互联网 发布:eclipse更改端口号 编辑:程序博客网 时间:2024/05/17 01:11

等待通知机制的实现

wait()和notify()方法只能在同步方法或者同步块中使用,否则会抛出 IllegalMonitorStateException!没有对象监视器!一个使线程停止,一个使停止的线程继续运行

执行wait方法后,当前线程释放锁,notify方法执行后不会马上释放对象锁,要都能线程将程序执行完。也就是退出synchronized代码块后,才会释放

ps:每个锁对象都有两个队列,一个人就绪队列(存储将要获得锁的线程),一个使阻塞队列(存储了被阻塞的线程)。一个线程被唤醒就会进入就绪队列,等待CPU的调度

一个线程内wait后 ,就会进入阻塞队列,等待下一次被唤醒!

interrupt方法遇到wait方法

try {
Object lock = new Object();
ThreadA t = new ThreadA(lock);
t.start();
Thread.sleep(5000);
t.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}

begin wait
java.lang.InterruptedException
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:503)
出现异常了,因为wait状态的线程被interrupt!

PS: 1执行完同步块中的代码就会释放对象的锁    

2 在执行同步块中的代码,遇到异常而导致线程终止,锁也会释放

3在执行同步块中的过程中,执行了锁所属对象的wait方法,这个线程会释放对象锁,而此线程对象会进入线程等待池中,等待被唤醒!

notify只能唤醒一个线程,要想唤醒所有线程,notifyAll()方法

通知过早问题:如果wait线程没执行,notify执行了 那么wait就没必要在执行了,加flag,在调用notify的时候将falg设置为false   则 while(flag){wait}就不会执行了

生产者和消费者模式:

操作值

一生产一个消费 操作值 交替运行

多生产多消费 操作值  出现 假死状态(全部线程处理waiting状态,则程序就不在执行任何业务功能了,整个项目呈停止状态!)

PS:wait\notify进行通信,不能保证notify唤醒的是异类,也许是同类,若生产唤醒生产,消费唤醒消费,最后积少成多,线程都处于假死状态

解决:通知的时候不只是通知同类,也通知异类,不使用notify使用notifyAll();

操作栈

一生产者一消费者:生产和消费交替执行

一生产与多消费:解决wait条件改变   if换成while与假死  notifyAll()

通过管道进行线程间通信:字节流

JDK提供了4个类使线程间可以进行通信:PipedInputStream  和PipedOutputStream PipedReader PipedWriter

字节流和字符流一样

inputStream.connect(outputStream)或者outputStream.connect(inputStream)使两个Stream之间产生通信连接,这样才可以将数据进行输入与输出

 等待/通知之交叉备份 很好的利用flag 在俩线程间切换

PS:

synchronized public void backupA() {
try {
while (prevIsA == true) {
wait();
}
for (int i = 0; i < 5; i++) {
System.out.println("☆☆☆☆☆");
}
prevIsA = true;
notifyAll();
} catch (Exception e) {
e.printStackTrace();
}
}
synchronized public void backupB() {
try {
while (prevIsA == false) {
wait();
}
for (int i = 0; i < 5; i++) {
System.out.println("★★★★★");
}
prevIsA = false;
notifyAll();
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
}
}


JOIN方法:等待当前调用join的线程对象销毁

join在内部使用wait方法进行等待,而synchronized关键字使用的是“对象监视器”原理作为同步

join和intrrupt方法遇到彼此,则会出现异常!

join(long)设置等待的时间!运行结果和sleep一样,只是在同步处理上不一样!PS:join的内部使用wait(long)方法来实现,所以join(long)具有释放锁的特点

ThreadLocal:类似于存放全局数据的盒子,解决变量在不同线程间的隔离性