Java多线程实战编程-----活例分析
Java多线程实战编程-----活例分析
以下给出一个 CS小框架底层的Communication类的实现,牵扯到 多线程的安全性问题
communication 可以为上层的conversation所用,里面创建了一个线程,这个线程用来侦听对端发过来的消息,而communication是被一个线程调用的,暂且称为主线程。 创建的侦听线程称为子线程。
我们要实现的是让 Communication的构造方法完成前 ,一定要让侦听线程 运行起来。
我们采取加锁的方法,接下来看看具体实现。
public abstract class Communication implements Runnable {
private Socket socket;
private DataInputStream dis;
private DataOutputStream dos;
private volatile boolean goon;
private Object lock;
Communication(Socket socket) {
try {
this.lock = new Object();
this.socket = socket;
this.dis = new DataInputStream(socket.getInputStream());
this.dos = new DataOutputStream(socket.getOutputStream());
synchronized (lock) {
this.goon = true;
new Thread(this, "COMMUNICATION").start();
// 如果这里也存在代码,则,它们可能在子线程真正运行之前执行。
try {
lock.wait();
// wait()方法,在阻塞自身线程前,必然开lock锁;
// 当该线程被其它线程notify()后,将再次进入lock锁块
//而进一步对lock上锁。
} catch (InterruptedException e) {
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
String message = null;
synchronized (lock) {
lock.notify();
}
while (goon) {
try {
message = dis.readUTF();
dealNetMessage(new NetMessage(message));
} catch (IOException e) {
if (goon == true) {
goon = false;
peerAbnormalDrop();
}
}
}
close();
}
-
初态,对象锁lock的开着的,主线程先进入到里面,然后将锁关闭,
当执行到第16行的时候,执行start()函数,这时子线程 进入就绪态,这时候就有两个线程,共同竞争CPU。 -
第一种情况 主线程时间片段用完,则执行子线程 进入run()方法,但是 33行 对象锁是关着的
(两个线程公用一把锁)故一直等待 直至时间片段耗完,而后进主线程到达17行,执行相关代码
第二种情况 主线程自己继续往下运行。这两种情况 都能够到底下这种情况
到了第19行,利用wait方法将自己阻塞,而将对象锁打开
这时候,就可以执行 子线程,子线程的锁刚好也是开着的,进去之后将锁关闭,并且唤醒 主线程,
使其进入就绪态
1.这时候 如果子线程时间片段到了,就进入主线程,而主线程,锁还是锁着的,
就又回到子线程,子线程,出锁之后,并执行 底下的read()
2. 若时间片段没有到的话,也就继续执行read()
这样就基本上实现了 Communication 构造方法运行结束前,侦听线程启动起来。
有的童鞋会说,可以将read()包含到锁里面,
那么这样会有什么问题呢?
注意: read( )也是一个线程,它像极了C语言的scanf(),一旦启动就会一直侦听下去,直到读取到内容才会执行下面的代码,这样的话,子线程就变成了死锁,无法继续往下执行。
好了,线程的实际应用就到这里,欢迎下方留言,指出不足,让我们携手共进!