一、通过管道进行线程间通信
1.1 管道流pipeStream
一种特殊的流,用于在不同线程之间直接传送数据。一个线程发送数据到输出管道,另一个线程从输入管道中取数据。通过使用管道,实现不同线程之间的通信,而无需借助于类似临时文件的东西。
1.2 jdk提供的用于线程通信的类
- PipedInputSream和PipedOutputStream
- PipedReader和PipedWriter
1.3 字节流方式读取
读数据:
public class readData {
public void readMehtod(PipedInputStream input) throws IOException {
System.out.println("Read开始了");
byte[] byteArray = new byte[20];
int flag = input.read(byteArray);
while(flag != -1){
String Data = new String(byteArray, 0, flag);
System.out.println(Data);
flag = input.read(byteArray);
}
input.close();
}
}
写数据:
public class writeData {
public void writeMethod(PipedOutputStream out) throws IOException {
System.out.println("write");
for (int i = 0; i < 300; i++) {
String outDate = " " + i;
out.write(outDate.getBytes());
System.out.println(outDate);
}
out.close();
}
}
读数据线程:
public class readThread extends Thread {
readData a;
PipedInputStream in;
public readThread(readData a, PipedInputStream in){
this.a = a;
this.in = in;
}
@Override
public void run() {
try {
a.readMehtod(in);
} catch (IOException e) {
e.printStackTrace();
}
}
}
写数据线程:
public class writeThread extends Thread{
writeData a;
PipedOutputStream out;
public writeThread(writeData a, PipedOutputStream out){
this.a = a;
this.out = out;
}
@Override
public void run() {
try {
a.writeMethod(out);
} catch (IOException e) {
e.printStackTrace();
}
}
}
测试方法:
public class test {
public static void main(String[] args) throws IOException {
PipedInputStream in = new PipedInputStream();
PipedOutputStream out = new PipedOutputStream();
in.connect(out);
readData a = new readData();
writeData b = new writeData();
writeThread write = new writeThread(b, out);
readThread read = new readThread(a, in);
write.start();
read.start();
}
}
1.4 字符流方式读取
读方法:
public class readData {
public void readMehtod(PipedReader input) throws IOException {
System.out.println("Read开始了");
char[] byteArray = new char[20];
int flag = input.read(byteArray);
while(flag != -1){
String Data = new String(byteArray, 0, flag);
System.out.println(Data);
flag = input.read(byteArray);
}
input.close();
}
}
写方法:
public class writeData {
public void writeMethod(PipedWriter out) throws IOException {
System.out.println("write");
for (int i = 0; i < 300; i++) {
String outDate = " " + i;
out.write(outDate);
System.out.println(outDate);
}
out.close();
}
}
只有管道中写入了数据,读线程才能读出数据,否则读线程会阻塞in.read(xx)方法上。
1.5 字符与字节的区别
https://www.cnblogs.com/mrjade/p/6861107.html
二、等待/通知交叉备份
2.1 问题描述
创建20个线程,10个线程将数据备份到A数据库中,10个线程将数据备份到B数据库中,并且备份到数据库A与备份到数据库B是交叉运行的。
2.2 解决
类代码:
package backup;
public class backup {
volatile private boolean flag = false;
synchronized public void backupA(){
while(flag == false){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + "*****");
}
//A备份完,轮到B
this.flag = false;
this.notifyAll();
}
synchronized public void backupB(){
while(flag == true){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + "-----");
}
//B备份完,轮到A
flag = true;
notifyAll();
}
}
A备份线程:
public class backupA extends Thread {
backup a;
public backupA(backup a){
this.a = a;
}
@Override
public void run() {
a.backupA();
}
}
B备份线程
package backup;
public class backupB extends Thread{
backup b;
public backupB(backup b){
this.b = b;
}
@Override
public void run() {
b.backupB();
}
}
运行类:
public class test {
public static void main(String[] args) {
backup backup = new backup();
for (int i = 0; i < 10; i++) {
backupA a = new backupA(backup);
a.start();
backupB b = new backupB(backup);
b.start();
}
}
}
结果:
Thread-1-----
Thread-1-----
Thread-1-----
Thread-1-----
Thread-1-----
Thread-0*****
Thread-0*****
Thread-0*****
Thread-0*****
Thread-0*****
.......