线程与线程之间不是独立个体,它们彼此是可以互相通信和协作的。
可以使用sleep()和while(true)死循环法来实现多个线程间的通信
拥有相同锁的线程才能实现该机制
该方法是Object类的方法,仅限锁对象调用。
new Thread()新建线程,调用start()方法到运行,调用stop()方法销毁。运行状态调用yield()出让cpu资源,调用suspend()、sleep()、wait()方法暂停线程,调用stop()、run()方法销毁。暂停状态调用resume()方法到运行,调用stop()方法销毁。
线程调用wait()方法后再对该线程对象执行interrupt()方法会出现Interrupted-Exception异常。
每调用一次notify()方法,只通知一个线程进行唤醒,唤醒的顺序与执行wait()方法的顺序一致。
带一个参数的wait(long)方法的功能是等待某一时间内是否有线程对锁进行notify()通知唤醒,如果超过这个时间则线程自动唤醒,能继续向下运行的前提是再次持有锁。
必须有锁才能向下运行,否则一直等待,直到有锁为止。
新增一个变量来控制通知顺序,由通知线程管理。
多线程会导致消费异常,需要使用while保证程序正确
解决假死:使用notifyAll()方法通知所有的类
import java.io.PipedInputStream;
/**
* @author 29467
* @date 2022/9/7 22:51
*/
public class ReadData {
public void readMethod(PipedInputStream input){
try{
System.out.println("read:");
byte[] byteArray = new byte[20];
int readLength = input.read(byteArray);
while(readLength != -1){
String newData = new String(byteArray,0,readLength);
System.out.println(newData);
readLength = input.read(byteArray);
}
System.out.println();
input.close();
}catch (Exception e){
e.printStackTrace();
}
}
}
import java.io.IOException;
import java.io.PipedOutputStream;
/**
* @author 29467
* @date 2022/9/7 22:44
*/
public class WriteData {
public void writeMethod(PipedOutputStream out){
try {
System.out.println("write:");
for(int i = 0; i<300;i++){
String outData = "" + (i+1);
out.write(outData.getBytes());
System.out.println(outData);
}
System.out.println();
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
import java.io.PipedInputStream;
/**
* @author 29467
* @date 2022/9/7 23:10
*/
public class ThreadRead extends Thread{
private ReadData read;
private PipedInputStream input;
public ThreadRead(ReadData read, PipedInputStream input) {
super();
this.read = read;
this.input = input;
}
@Override
public void run() {
read.readMethod(input);
}
}
import java.io.PipedOutputStream;
/**
* @author 29467
* @date 2022/9/7 23:07
*/
public class ThreadWrite extends Thread{
private WriteData writeData;
private PipedOutputStream out;
public ThreadWrite(WriteData writeData, PipedOutputStream out){
super();
this.writeData = writeData;
this.out = out;
}
@Override
public void run() {
writeData.writeMethod(out);
}
}
import java.io.IOException;
import java.io.PipedInputStream;
import java.io.PipedOutputStream;
/**
* @author 29467
* @date 2022/9/7 23:12
*/
public class Run {
public static void main(String[] args) {
try{
WriteData writeData = new WriteData();
ReadData readData = new ReadData();
PipedInputStream inputStream = new PipedInputStream();
PipedOutputStream outputStream = new PipedOutputStream();
outputStream.connect(inputStream);
ThreadRead threadRead = new ThreadRead(readData,inputStream);
threadRead.start();
Thread.sleep(2000);
ThreadWrite threadWrite = new ThreadWrite(writeData,outputStream);
threadWrite.start();
}catch (IOException e){
e.printStackTrace();
}catch (InterruptedException e){
e.printStackTrace();
}
}
}
利用notifyAll()和volatile变量来实现交叉备份
他的作用是等待线程对象销毁,会使得当前线程暂停等待(内部是wait()方法)
join()和interrupt()方法彼此遇到会出现异常,不论先后
参数用于设置等待的时间,不管x线程是否执行完毕,时间到了并且重新获得了锁,则当前线程会继续向后运行。如果没有重新获得锁,则一直在尝试,知道获得锁为止。
join(long)方法的功能是在内部是使用wait(long)方法来进行实现的,所以join(long)方法具有释放锁的特点
原因:线程run()方法的随机性
参数为毫秒和纳秒
一个ThreadLocal对象对应一个value
如果ThreadLocal没有对应的value值则返回null,如果有值则get()方法返回对应的值。
ThreadLocal将值存到ThreadLocalMap中
线程可以从ThreadLocal里取出自己的值,不能取出其他线程的值
重写ThreadLocal的initialValue()方法,返回的值为默认值。
使用该类可以使子线程继承父线程的值
要继承的话用类InheritableThreadLocal
详见源代码