本章内容:
- 数据结构和容器
- 简单的同步例子
- 一个网络服务器类
- AsyncInputStream 类
- 使用 TCPServer 和 AsyncInputStream
一 数据结构和容器
消息队列:
//
ch05.MsgQueue.java
import java.util. * ;
public class MsgQueue ... {
Vector queue = new Vector();
public synchronized void send(Object obj) ...{
queue.addElement(obj);
}
public synchronized Object recv() ...{
if (queue.size() == 0) return null;
Object obj = queue.firstElement();
queue.removeElementAt(0);
return obj;
}
}
import java.util. * ;
public class MsgQueue ... {
Vector queue = new Vector();
public synchronized void send(Object obj) ...{
queue.addElement(obj);
}
public synchronized Object recv() ...{
if (queue.size() == 0) return null;
Object obj = queue.firstElement();
queue.removeElementAt(0);
return obj;
}
}
共享内存:
//
ch05.ShareMemory.java
public class ShareMemory extends BusyFlag ... {
byte memory[];
public ShareMemory (int size) ...{
memory = new byte[size];
}
public synchronized byte[] attach() ...{
getBusyFlag();
return memory;
}
public synchronized void detach() ...{
freeBusyFlag();
}
}
public class ShareMemory extends BusyFlag ... {
byte memory[];
public ShareMemory (int size) ...{
memory = new byte[size];
}
public synchronized byte[] attach() ...{
getBusyFlag();
return memory;
}
public synchronized void detach() ...{
freeBusyFlag();
}
}
循环链表:
//
ch05.CircularListNode.java
class CircularListNode ... {
Object o;
CircularListNode next;
CircularListNode prev;
}
// ch05.CircularList.java
public class CircularList ... {
private CircularListNode current;
public synchronized void insert(Object o) ...{
CircularListNode tn = new CircularListNode();
tn.o = o;
if (current == null) ...{
tn.next = tn.prev = tn;
current = tn;
} else ...{ // Add Before Current Node
tn.next = current;
tn.prev = current.prev;
current.prev.next = tn;
current.prev = tn;
}
}
public synchronized void delete(Object o) ...{
CircularListNode p = find(o);
CircularListNode next = p.next;
CircularListNode prev = p.prev;
if (p == p.next) ...{ // Last Object on the list
current = null;
return;
}
prev.next = next;
next.prev = prev;
if (current == p) current = next;
}
private CircularListNode find(Object o) ...{
CircularListNode p = current;
if (p == null)
throw new IllegalArgumentException();
do ...{
if (p.o == o) return p;
p = p.next;
} while (p != current);
throw new IllegalArgumentException();
}
public synchronized Object locate(Object o) ...{
CircularListNode p = current;
do ...{
if (p.o.equals(o)) return p.o;
p = p.next;
} while (p != current);
throw new IllegalArgumentException();
}
public synchronized Object getNext() ...{
if (current == null)
return null;
current = current.next;
return current.o;
}
}
class CircularListNode ... {
Object o;
CircularListNode next;
CircularListNode prev;
}
// ch05.CircularList.java
public class CircularList ... {
private CircularListNode current;
public synchronized void insert(Object o) ...{
CircularListNode tn = new CircularListNode();
tn.o = o;
if (current == null) ...{
tn.next = tn.prev = tn;
current = tn;
} else ...{ // Add Before Current Node
tn.next = current;
tn.prev = current.prev;
current.prev.next = tn;
current.prev = tn;
}
}
public synchronized void delete(Object o) ...{
CircularListNode p = find(o);
CircularListNode next = p.next;
CircularListNode prev = p.prev;
if (p == p.next) ...{ // Last Object on the list
current = null;
return;
}
prev.next = next;
next.prev = prev;
if (current == p) current = next;
}
private CircularListNode find(Object o) ...{
CircularListNode p = current;
if (p == null)
throw new IllegalArgumentException();
do ...{
if (p.o == o) return p;
p = p.next;
} while (p != current);
throw new IllegalArgumentException();
}
public synchronized Object locate(Object o) ...{
CircularListNode p = current;
do ...{
if (p.o.equals(o)) return p.o;
p = p.next;
} while (p != current);
throw new IllegalArgumentException();
}
public synchronized Object getNext() ...{
if (current == null)
return null;
current = current.next;
return current.o;
}
}
二 简单的同步例子
屏障:
//
ch05.Barrier.java
public class Barrier ... {
private int threads2Wait4;
private InterruptedException iex;
public Barrier (int nThreads) ...{
threads2Wait4 = nThreads;
}
public synchronized int waitForRest()
throws InterruptedException ...{
int threadNum = --threads2Wait4;
if (iex != null) throw iex;
if (threads2Wait4 <= 0) ...{
notifyAll();
return threadNum;
}
while (threads2Wait4 > 0) ...{
if (iex != null) throw iex;
try ...{
wait();
} catch (InterruptedException ex) ...{
iex = ex;
notifyAll();
}
}
return threadNum;
}
public synchronized void freeAll() ...{
iex = new InterruptedException("Barrier Released by freeAll");
notifyAll();
}
}
public class Barrier ... {
private int threads2Wait4;
private InterruptedException iex;
public Barrier (int nThreads) ...{
threads2Wait4 = nThreads;
}
public synchronized int waitForRest()
throws InterruptedException ...{
int threadNum = --threads2Wait4;
if (iex != null) throw iex;
if (threads2Wait4 <= 0) ...{
notifyAll();
return threadNum;
}
while (threads2Wait4 > 0) ...{
if (iex != null) throw iex;
try ...{
wait();
} catch (InterruptedException ex) ...{
iex = ex;
notifyAll();
}
}
return threadNum;
}
public synchronized void freeAll() ...{
iex = new InterruptedException("Barrier Released by freeAll");
notifyAll();
}
}
条件变量:
//
ch05.CondVar.java
public class CondVar ... {
private BusyFlag SyncVar;
public CondVar() ...{
this(new BusyFlag());
}
public CondVar(BusyFlag sv) ...{
SyncVar = sv;
}
public void cvWait() throws InterruptedException ...{
cvTimedWait(SyncVar, 0);
}
public void cvWait(BusyFlag sv) throws InterruptedException ...{
cvTimedWait(sv, 0);
}
public void cvTimedWait(int millis) throws InterruptedException ...{
cvTimedWait(SyncVar, millis);
}
public void cvTimedWait(BusyFlag sv, int millis) throws InterruptedException ...{
int i = 0;
InterruptedException errex = null;
synchronized (this) ...{
// You must own the lock in order to use this method
if (sv.getBusyFlagOwner() != Thread.currentThread()) ...{
throw new IllegalMonitorStateException("current thread not owner");
}
// Release the lock (Completely)
while (sv.getBusyFlagOwner() == Thread.currentThread()) ...{
i++;
sv.freeBusyFlag();
}
// Use wait() method
try ...{
if (millis == 0) ...{
wait();
} else ...{
wait(millis);
}
} catch (InterruptedException iex) ...{
errex = iex;
}
}
// Obtain the lock (Return to original state)
for (; i>0; i--) ...{
sv.getBusyFlag();
}
if (errex != null) throw errex;
return;
}
public void cvSignal() ...{
cvSignal(SyncVar);
}
public synchronized void cvSignal(BusyFlag sv) ...{
// You must own the lock in order to use this method
if (sv.getBusyFlagOwner() != Thread.currentThread()) ...{
throw new IllegalMonitorStateException("current thread not owner");
}
notify();
}
public void cvBroadcast() ...{
cvBroadcast(SyncVar);
}
public synchronized void cvBroadcast(BusyFlag sv) ...{
// You must own the lock in order to use this method
if (sv.getBusyFlagOwner() != Thread.currentThread()) ...{
throw new IllegalMonitorStateException("current thread not owner");
}
notifyAll();
}
}
public class CondVar ... {
private BusyFlag SyncVar;
public CondVar() ...{
this(new BusyFlag());
}
public CondVar(BusyFlag sv) ...{
SyncVar = sv;
}
public void cvWait() throws InterruptedException ...{
cvTimedWait(SyncVar, 0);
}
public void cvWait(BusyFlag sv) throws InterruptedException ...{
cvTimedWait(sv, 0);
}
public void cvTimedWait(int millis) throws InterruptedException ...{
cvTimedWait(SyncVar, millis);
}
public void cvTimedWait(BusyFlag sv, int millis) throws InterruptedException ...{
int i = 0;
InterruptedException errex = null;
synchronized (this) ...{
// You must own the lock in order to use this method
if (sv.getBusyFlagOwner() != Thread.currentThread()) ...{
throw new IllegalMonitorStateException("current thread not owner");
}
// Release the lock (Completely)
while (sv.getBusyFlagOwner() == Thread.currentThread()) ...{
i++;
sv.freeBusyFlag();
}
// Use wait() method
try ...{
if (millis == 0) ...{
wait();
} else ...{
wait(millis);
}
} catch (InterruptedException iex) ...{
errex = iex;
}
}
// Obtain the lock (Return to original state)
for (; i>0; i--) ...{
sv.getBusyFlag();
}
if (errex != null) throw errex;
return;
}
public void cvSignal() ...{
cvSignal(SyncVar);
}
public synchronized void cvSignal(BusyFlag sv) ...{
// You must own the lock in order to use this method
if (sv.getBusyFlagOwner() != Thread.currentThread()) ...{
throw new IllegalMonitorStateException("current thread not owner");
}
notify();
}
public void cvBroadcast() ...{
cvBroadcast(SyncVar);
}
public synchronized void cvBroadcast(BusyFlag sv) ...{
// You must own the lock in order to use this method
if (sv.getBusyFlagOwner() != Thread.currentThread()) ...{
throw new IllegalMonitorStateException("current thread not owner");
}
notifyAll();
}
}
三 一个网络服务器类
//
ch05.TCPServer.java
import java.net. * ;
import java.io. * ;
public class TCPServer implements Cloneable, Runnable ... {
Thread runner = null;
ServerSocket server = null;
Socket data = null;
boolean shouldStop = false;
public synchronized void startServer(int port) throws IOException ...{
if (runner == null) ...{
server = new ServerSocket(port);
runner = new Thread(this);
runner.start();
}
}
public synchronized void stopServer() ...{
if (server != null) ...{
shouldStop = true;
runner.interrupt();
runner = null;
try ...{
server.close();
} catch (IOException ioe) ...{}
server = null;
}
}
public void run() ...{
if (server != null) ...{
while (!shouldStop) ...{
try ...{
Socket datasocket = server.accept();
TCPServer newSocket = (TCPServer) clone();
newSocket.server = null;
newSocket.data = datasocket;
newSocket.runner = new Thread(newSocket);
newSocket.runner.start();
} catch (Exception e) ...{}
}
} else ...{
run(data);
}
}
public void run(Socket data) ...{
}
}
import java.net. * ;
import java.io. * ;
public class TCPServer implements Cloneable, Runnable ... {
Thread runner = null;
ServerSocket server = null;
Socket data = null;
boolean shouldStop = false;
public synchronized void startServer(int port) throws IOException ...{
if (runner == null) ...{
server = new ServerSocket(port);
runner = new Thread(this);
runner.start();
}
}
public synchronized void stopServer() ...{
if (server != null) ...{
shouldStop = true;
runner.interrupt();
runner = null;
try ...{
server.close();
} catch (IOException ioe) ...{}
server = null;
}
}
public void run() ...{
if (server != null) ...{
while (!shouldStop) ...{
try ...{
Socket datasocket = server.accept();
TCPServer newSocket = (TCPServer) clone();
newSocket.server = null;
newSocket.data = datasocket;
newSocket.runner = new Thread(newSocket);
newSocket.runner.start();
} catch (Exception e) ...{}
}
} else ...{
run(data);
}
}
public void run(Socket data) ...{
}
}
//
ch05.ServerHandler.java
import java.net. * ;
import java.io. * ;
public class ServerHandler extends TCPServer ... {
public void run(Socket data) ...{
try ...{
InputStream is = data.getInputStream();
OutputStream os = data.getOutputStream();
// Process the data socket here
} catch (Exception e) ...{}
}
}
import java.net. * ;
import java.io. * ;
public class ServerHandler extends TCPServer ... {
public void run(Socket data) ...{
try ...{
InputStream is = data.getInputStream();
OutputStream os = data.getOutputStream();
// Process the data socket here
} catch (Exception e) ...{}
}
}
//
ch05.MyServer.java
import java.net. * ;
import java.io. * ;
public class MyServer ... {
public static void main(String args[]) throws Exception ...{
TCPServer serv = new ServerHandler();
serv.startServer(300);
}
}
import java.net. * ;
import java.io. * ;
public class MyServer ... {
public static void main(String args[]) throws Exception ...{
TCPServer serv = new ServerHandler();
serv.startServer(300);
}
}
四 AsyncInputStream 类
//
ch05.AsyncInputStream.java
import java.net. * ;
import java.io. * ;
public class AsyncInputStream extends FilterInputStream implements Runnable ... {
private Thread runner; // Async Reader Thread
private byte result[]; // Buffer
private int reslen; // Buffer Length
private boolean EOF; // End-of-File Indicator
private IOException IOError; // IOExceptions
BusyFlag lock; // Data Lock
CondVar empty, full; // Signal Variables
protected AsyncInputStream(InputStream in, int bufsize) ...{
super(in);
lock = new BusyFlag(); // Allocate sync variables
empty = new CondVar(lock);
full = new CondVar(lock);
result = new byte[bufsize]; // Allocate Storage Area
reslen = 0; // and initialize variables
EOF = false;
IOError = null;
runner = new Thread(this); // Start Reader Thread
runner.start();
}
protected AsyncInputStream(InputStream in) ...{
this(in, 1024);
}
public int read() throws IOException ...{
try ...{
lock.getBusyFlag();
while (reslen == 0) ...{
try ...{
if (EOF) return(-1);
if (IOError != null) throw IOError;
empty.cvWait();
} catch (InterruptedException e) ...{}
}
return (int) getChar();
} finally ...{
lock.freeBusyFlag();
}
}
public int read(byte b[]) throws IOException ...{
return read(b, 0, b.length);
}
public int read(byte b[], int off, int len) throws IOException ...{
try ...{
lock.getBusyFlag();
while (reslen == 0) ...{
try ...{
if (EOF) return(-1);
if (IOError != null) throw IOError;
empty.cvWait();
} catch (InterruptedException e) ...{}
}
int sizeread = Math.min(reslen, len);
byte c[] = getChars(sizeread);
System.arraycopy(c, 0, b, off, sizeread);
return(sizeread);
} finally ...{
lock.freeBusyFlag();
}
}
public long skip(long n) throws IOException ...{
try ...{
lock.getBusyFlag();
int sizeskip = Math.min(reslen, (int) n);
if (sizeskip > 0) ...{
byte c[] = getChars(sizeskip);
}
return((long)sizeskip);
} finally ...{
lock.freeBusyFlag();
}
}
public int available() throws IOException ...{
return reslen;
}
public void close() throws IOException ...{
try ...{
lock.getBusyFlag();
reslen = 0; // Clear Buffer
EOF = true; // Mark End Of File
empty.cvBroadcast(); // Alert all Threads
full.cvBroadcast();
} finally ...{
lock.freeBusyFlag();
}
}
public void mark(int readlimit) ...{
}
public void reset() throws IOException ...{
}
public boolean markSupported() ...{
return false;
}
public void run() ...{
try ...{
while (true) ...{
int c = in.read();
try ...{
lock.getBusyFlag();
if ((c == -1) || (EOF)) ...{
EOF = true; // Mark End Of File
in.close(); // Close Input Source
return; // End IO Thread
} else ...{
putChar((byte)c); // Store the byte read
}
if (EOF) ...{
in.close(); // Close Input Source
return; // End IO Thread
}
} finally ...{
lock.freeBusyFlag();
}
}
} catch (IOException e) ...{
IOError = e; // Store Exception
return;
} finally ...{
try ...{
lock.getBusyFlag();
empty.cvBroadcast(); // Alert all Threads
} finally ...{
lock.freeBusyFlag();
}
}
}
private void putChar(byte c) ...{
try ...{
lock.getBusyFlag();
while ((reslen == result.length) && (!EOF)) ...{
try ...{
full.cvWait();
} catch (InterruptedException ie) ...{}
}
if (!EOF) ...{
result[reslen++] = c;
empty.cvSignal();
}
} finally ...{
lock.freeBusyFlag();
}
}
private byte getChar() ...{
try ...{
lock.getBusyFlag();
byte c = result[0];
System.arraycopy(result, 1, result, 0, --reslen);
full.cvSignal();
return c;
} finally ...{
lock.freeBusyFlag();
}
}
private byte[] getChars(int chars) ...{
try ...{
lock.getBusyFlag();
byte c[] = new byte[chars];
System.arraycopy(result, 0, c, 0, chars);
reslen -= chars;
System.arraycopy(result, chars, result, 0, reslen);
full.cvSignal();
return c;
} finally ...{
lock.freeBusyFlag();
}
}
}
import java.net. * ;
import java.io. * ;
public class AsyncInputStream extends FilterInputStream implements Runnable ... {
private Thread runner; // Async Reader Thread
private byte result[]; // Buffer
private int reslen; // Buffer Length
private boolean EOF; // End-of-File Indicator
private IOException IOError; // IOExceptions
BusyFlag lock; // Data Lock
CondVar empty, full; // Signal Variables
protected AsyncInputStream(InputStream in, int bufsize) ...{
super(in);
lock = new BusyFlag(); // Allocate sync variables
empty = new CondVar(lock);
full = new CondVar(lock);
result = new byte[bufsize]; // Allocate Storage Area
reslen = 0; // and initialize variables
EOF = false;
IOError = null;
runner = new Thread(this); // Start Reader Thread
runner.start();
}
protected AsyncInputStream(InputStream in) ...{
this(in, 1024);
}
public int read() throws IOException ...{
try ...{
lock.getBusyFlag();
while (reslen == 0) ...{
try ...{
if (EOF) return(-1);
if (IOError != null) throw IOError;
empty.cvWait();
} catch (InterruptedException e) ...{}
}
return (int) getChar();
} finally ...{
lock.freeBusyFlag();
}
}
public int read(byte b[]) throws IOException ...{
return read(b, 0, b.length);
}
public int read(byte b[], int off, int len) throws IOException ...{
try ...{
lock.getBusyFlag();
while (reslen == 0) ...{
try ...{
if (EOF) return(-1);
if (IOError != null) throw IOError;
empty.cvWait();
} catch (InterruptedException e) ...{}
}
int sizeread = Math.min(reslen, len);
byte c[] = getChars(sizeread);
System.arraycopy(c, 0, b, off, sizeread);
return(sizeread);
} finally ...{
lock.freeBusyFlag();
}
}
public long skip(long n) throws IOException ...{
try ...{
lock.getBusyFlag();
int sizeskip = Math.min(reslen, (int) n);
if (sizeskip > 0) ...{
byte c[] = getChars(sizeskip);
}
return((long)sizeskip);
} finally ...{
lock.freeBusyFlag();
}
}
public int available() throws IOException ...{
return reslen;
}
public void close() throws IOException ...{
try ...{
lock.getBusyFlag();
reslen = 0; // Clear Buffer
EOF = true; // Mark End Of File
empty.cvBroadcast(); // Alert all Threads
full.cvBroadcast();
} finally ...{
lock.freeBusyFlag();
}
}
public void mark(int readlimit) ...{
}
public void reset() throws IOException ...{
}
public boolean markSupported() ...{
return false;
}
public void run() ...{
try ...{
while (true) ...{
int c = in.read();
try ...{
lock.getBusyFlag();
if ((c == -1) || (EOF)) ...{
EOF = true; // Mark End Of File
in.close(); // Close Input Source
return; // End IO Thread
} else ...{
putChar((byte)c); // Store the byte read
}
if (EOF) ...{
in.close(); // Close Input Source
return; // End IO Thread
}
} finally ...{
lock.freeBusyFlag();
}
}
} catch (IOException e) ...{
IOError = e; // Store Exception
return;
} finally ...{
try ...{
lock.getBusyFlag();
empty.cvBroadcast(); // Alert all Threads
} finally ...{
lock.freeBusyFlag();
}
}
}
private void putChar(byte c) ...{
try ...{
lock.getBusyFlag();
while ((reslen == result.length) && (!EOF)) ...{
try ...{
full.cvWait();
} catch (InterruptedException ie) ...{}
}
if (!EOF) ...{
result[reslen++] = c;
empty.cvSignal();
}
} finally ...{
lock.freeBusyFlag();
}
}
private byte getChar() ...{
try ...{
lock.getBusyFlag();
byte c = result[0];
System.arraycopy(result, 1, result, 0, --reslen);
full.cvSignal();
return c;
} finally ...{
lock.freeBusyFlag();
}
}
private byte[] getChars(int chars) ...{
try ...{
lock.getBusyFlag();
byte c[] = new byte[chars];
System.arraycopy(result, 0, c, 0, chars);
reslen -= chars;
System.arraycopy(result, chars, result, 0, reslen);
full.cvSignal();
return c;
} finally ...{
lock.freeBusyFlag();
}
}
}
五 使用 TCPServer 和 AsyncInputStream
//
ch05.ServerHandler2.java
import java.net. * ;
import java.io. * ;
public class ServerHandler2 extends TCPServer ... {
public void run(Socket data) ...{
try ...{
InputStream is =
new AsyncInputStream(data.getInputStream());
OutputStream os = data.getOutputStream();
// Process the data socket here
} catch (Exception e) ...{}
}
}
import java.net. * ;
import java.io. * ;
public class ServerHandler2 extends TCPServer ... {
public void run(Socket data) ...{
try ...{
InputStream is =
new AsyncInputStream(data.getInputStream());
OutputStream os = data.getOutputStream();
// Process the data socket here
} catch (Exception e) ...{}
}
}