您的位置:首页 > 大数据 > 人工智能

主线程wait等待子线程返回对象信息

2017-07-04 13:47 399 查看
需求:假设一个线程(JarThread)正在从网络连接(用System.in模拟)中读取一个JAR归档文件。这个归档文件中第一项是清单文件(用‘/’标识结束)。另一个线程(MainThread)可能对这个清单文件的内容感兴趣,即使归档文件的其余部分尚不可用。对清单文件感兴趣的线程会创建一个定制的ManifestFile对象,将这个对象的引用传递给将要读取JAR归档文件的线程,并等待这个对象。读取归档文件的线程首先用流中的项填写ManifestFile,然后通知ManifestFile,再继续读取JAR归档文件的其余部分。当阅读器线程通知ManifestFile时,原来的线程会被唤醒,按其计划处理现在已经完全准备就绪的ManifestFile对象

1.       JarThread

public class JarThread implements Runnable {

Logger logger = LoggerFactory.getLogger(JarThread.class);

ManifestFile manifestFile;
InputStream in;

public JarThread(ManifestFile m, InputStream in) {
this.manifestFile = m;
this.in = in;
}

@Override
public void run() {
int i;
//与MainThread获取同一个对象锁
synchronized (manifestFile) {
//从流in中读入清单文件
try {
while ((i = in.read()) != -1) {
//如果字符/ 标志MainThread感兴趣的内容结束
if(i==47){
break;
}
manifestFile.add(i);
}
} catch (IOException e) {
e.printStackTrace();
}
//释放对象锁
manifestFile.notifyAll();
}
//读取流的其他部分
try {
while ((i = in.read()) != -1) {
logger.info(String.valueOf((char)i));
}
} catch (IOException e) {
e.printStackTrace();
}
}
}

2.      ManifestFile

public class ManifestFile {

private StringBuffer content = new StringBuffer();

public synchronized StringBuffer getContent() {
return content;
}

public synchronized void add(int i) {
content.append((char)(i));
}
}

3.       MainThread

public class MainThread {
final static Logger logger = LoggerFactory.getLogger(MainThread.class);
public static void main(String[] args) throws IOException {
InputStream in = System.in;
//system.in如何判断读到了
ManifestFile m = new ManifestFile();
//启动读取线程 这里的需求比较特别
//并不是从线程中返回 而是返回所需要的部分,而线程继续执行
JarThread t = new JarThread(m, in);
ExecutorService exec = Executors.newCachedThreadPool();

//首先获取对象锁
synchronized (m) {
exec.execute(t);
try {
//挂起 释放锁 等待JarThread通知
m.wait();
//处理清单文件
logger.info(m.getContent().toString());
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

4.       执行结果

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: