有一项任务:使用 AsynchronousSocketChannel 进行多线程执行功能。为了模拟服务器端的长时间工作,我使用 Thread.sleep()(存储在类Worker中)。如果我的线程超过2秒,当使用 ByteBuffer 和未来在客户端使用数据时,苍蝇 java.lang.IndexOutOfBoundsException < / strong>(我的函数 printFuncResult )请告诉我,我的问题是什么?服务器:
public class Server {
public static final InetSocketAddress hostAddress = new InetSocketAddress("localhost", 5678);
private AsynchronousServerSocketChannel serverChannel;
private AsynchronousSocketChannel clientChannel;
ExecutorService threadPool;
public Server() throws IOException, ExecutionException, InterruptedException {
serverChannel = AsynchronousServerSocketChannel.open();
serverChannel.bind(hostAddress);
System.out.println("Server channel bound to port: " + hostAddress.getPort());
System.out.println("Waiting for client to connect... ");
getClientChannel();
handleArguments();
}
private void getClientChannel() throws ExecutionException, InterruptedException {
Future<AsynchronousSocketChannel> acceptResult = serverChannel.accept();
clientChannel = acceptResult.get();
}
private void handleArguments() throws IOException, InterruptedException {
if ((clientChannel != null) && (clientChannel.isOpen())) {
ByteBuffer buffer = ByteBuffer.allocate(32);
Future<Integer> result = clientChannel.read(buffer);
while (! result.isDone()) {
// System.out.println("Result coming... ");
}
buffer.flip();
int x = buffer.getInt(0);
Worker workerOne = new Worker(Worker.TYPE_F, x, clientChannel);
Worker workerTwo = new Worker(Worker.TYPE_G, x, clientChannel);
threadPool = Executors.newFixedThreadPool(2);
threadPool.execute(workerOne);
threadPool.execute(workerTwo);
Thread.sleep(3000);
clientChannel.close();
}
}
}
class Worker implements Runnable {
public static final int TYPE_F = 1;
public static final int TYPE_G = 2;
private int x;
private int type;
private AsynchronousSocketChannel clientChannel;
public Worker(int type, int x, AsynchronousSocketChannel clientChannel) {
this.x = x;
this.type = type;
this.clientChannel = clientChannel;
}
private void sendResultToClient(int res) {
ByteBuffer buffer = ByteBuffer.allocate(32);
if (type == TYPE_F) {
res = 4545;
} else {
res = 34234;
}
buffer.putInt(0, type);
buffer.putInt(4, res);
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 10000; ++i) {
for (int j = 0; j < 10000; ++j) {
int k = i*j + i/(j +1) + i + j + Math.max(i, j);
}
}
boolean written = false;
while (!written) {
try {
clientChannel.write(buffer);
written = true;
} catch (Exception e) {}
}
}
@Override
public void run() {
int result = -1;
Random random = new Random();
switch (type) {
case TYPE_F :
result = (int)Math.pow(x, x);
break;
case TYPE_G :
result = (int)Math.pow(x, x / 2);
break;
}
sendResultToClient(result);
}
}
客户端:
public class Client {
private AsynchronousSocketChannel clientChannel;
ExecutorService threadPool;
public Client(int x) throws IOException, InterruptedException, ExecutionException {
threadPool = Executors.newFixedThreadPool(2);
boolean connected = false;
while (!connected) {
try {
clientChannel = AsynchronousSocketChannel.open();
Future<Void> future = clientChannel.connect(Server.hostAddress);
future.get();
connected = true;
} catch (ExecutionException e) {}
}
System.out.println("Client is started: " + clientChannel.isOpen());
System.out.println("Sending messages to server: ");
sendArguments(x);
//showCancelDialog();
listenResult();
clientChannel.close();
}
private void sendArguments(int x) throws InterruptedException, IOException {
ByteBuffer buffer = ByteBuffer.allocate(32);
buffer.putInt(0, x);
Future<Integer> result = clientChannel.write(buffer);
while (! result.isDone()) {
System.out.println("... ");
}
}
private boolean waitForResult(Future <Pair <Integer, Integer>> futureResult) {
Scanner sc = new Scanner(System.in);
while (!futureResult.isDone() ) {
System.out.println("DOING.. break? (y/n)");
String input = sc.next();
if (input.equals("y")) {
System.out.println("CANCELLED");
threadPool.shutdownNow();
return false;
}
}
return true;
}
private void printFuncResult(Future <Pair <Integer, Integer>> futureResult) throws ExecutionException, InterruptedException {
Integer funcType = new Integer(futureResult.get().getKey());
Integer result = new Integer(futureResult.get().getValue());
System.out.println("RESULT OF "+ funcType +" FUNC = " + result);
}
private void listenResult() throws ExecutionException, InterruptedException {
System.out.println("Wating for result...");
Listener listener = new Listener(clientChannel);
Future <Pair <Integer, Integer>> futureResult = threadPool.submit(listener);
if (!waitForResult(futureResult)) {
return;
}
printFuncResult(futureResult);
futureResult = threadPool.submit(listener);
if (!waitForResult(futureResult)) {
return;
}
printFuncResult(futureResult);
}
}
class Listener implements Callable <Pair <Integer, Integer>> {
private AsynchronousSocketChannel clientChannel;
public Listener(AsynchronousSocketChannel channel) {
this.clientChannel = channel;
}
@Override
public Pair <Integer, Integer> call() throws Exception {
ByteBuffer buffer = ByteBuffer.allocate(32);
Future<Integer> futureResult = clientChannel.read(buffer);
while (! futureResult.isDone()) {}
buffer.flip();
Integer type = new Integer(buffer.getInt(0));
Integer result = new Integer (buffer.getInt(4));
return new Pair<Integer, Integer>(type, result);
}
}
}
答案 0 :(得分:0)
IndexOutOfBoundsException不是来自printFuncResult。它仅存储在将来并在那里打印堆栈跟踪。 IndexOutOfBoundsException在此行的Listener调用函数中生成:
Integer type = new Integer(buffer.getInt(0));
如果读取没有读取足够数量的字节,则会发生这种情况。
我建议你替换这种低效且难以调试的循环。
while (! futureResult.isDone()) {}
类似
int bytes_read = futureResult.get();
if(bytes_read != 32) {
// log error or throw exception or retry ...
}