wait和notify都是object类的方法。
wait()是线程停止运行,notify()使停止的线程继续运行。
在调用wait和notify时,必须获得对象级锁,因此必须在同步方法或者同步代码块中执行。
wait:释放的对象锁-->该锁被其他线程获取,-->获取该锁的线程调用notify并执行完毕释放对象锁-->原来调用wait方法的对象重新获得对象锁-->继续执行
示例代码:
MyThread1.java
package zzzztrhead;
public class MyThread1 extends Thread {
private Object lock;
public MyThread1(Object lock) {
super();
this.lock = lock;
}
@Override
public void run() {
synchronized (lock) {
try {
System.out.println("开始wait");
lock.wait();
System.out.println("结束wait");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
lock.wait();
System.out.println("结束wait");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
MyThread2.java:
package zzzztrhead;
public class MyThread2 extends Thread {
private Object lock;
public MyThread2(Object lock) {
super();
this.lock = lock;
}
@Override
public void run() {
synchronized (lock) {
System.out.println("开始notify");
lock.notify();
System.out.println("结束notify");
}
}
}
lock.notify();
System.out.println("结束notify");
}
}
}
Test:
package zzzztrhead;
public class WaitNotifyTest {
public static void main(String []args) throws InterruptedException{
Object lock=new Object();
MyThread1 t1=new MyThread1(lock);
t1.start();
Thread.sleep(3000);//main线程让出cpu
MyThread2 t2=new MyThread2(lock);
t2.start();
}
}
执行结果:
开始wait
开始notify
结束notify
结束wait
由执行结果也可以看出:wait释放对象锁,notify不释放,必须等待执行notify的同步方法或代码块执行完才释放。
个人理解的:
wait释放的对象锁-->该锁被其他线程获取,-->获取该锁的线程调用notify并执行完毕释放对象锁-->原来调用wait方法的对象重新获得对象锁-->继续执行
1.PipedInputStream和PipedOutputStream(字节流)
2.PipedReader和PipedWriter(字符流)
*(outputStream.connect(inputStream);)
作用:使所属线程对象x正常执行run方法中的任务,使当前线程无线阻塞,等待线程x销毁后再继续执行线程z后面的代码。
在内部使用wait方法进行等待,
源码:
public final void join() throws InterruptedException {
join(0);
}
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);//使调用join方法的线程等待
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
还有一点:
t1.wait(); // 不是使t1线程等待,而是当前执行wait的线程等待
4.ThreadLocal的使用
每个线程绑定自己的值,可以将ThreadLocal类比喻成全局存放数据的盒子,盒子中可以存储每个线程的私有数据。
ThreadLocal源码解析:https://www.cnblogs.com/dennyzhangdd/p/7978455.html#_label0_0
操作一个内部类对象ThreadLocalMap,key=当前线程,value=线程局部变量。数据结构以及get,扩容等等类似于hashmap,set解决冲突用的开放定址法。
InheritableThreadLocal可以让子线程从父线程中取得值。(在线程初始化时,将赋值过去,可通过重写childeVlue方法来修改子线程继承自父线程的值)