我目前正在开发基于包commons.net的ftp客户端,以便运行测试以查看连接的速度。 基本上我的ftp测试包括连接到服务器,登录到它,然后根据需要开始下载/上传循环,直到用户决定通过按钮停止它,然后当前循环将结束,所以测试
然而,在运行这些测试时,出现了一种需要机制的情况。服务器正在传输文件,并在确实完成之前发送返回代码226(传输完成)。
所以我的线程仍然卡住,试图在不再可能的情况下清空inputStream。
我的想法是在下载过程中启动一个线程计时器,每次将一个字节传输到我的客户端时都会重置。 当超时发生时,会引发异常,并且我的客户端会对此作出反应,并进行下载。
我已阅读并尝试了许多解决方案,其中包括: - 从线程中引发异常 - >线程捕获异常而不是客户端; - 从线程中断客户端,因此客户端引发一个interruptException - >似乎不起作用; - 使用具有超时的执行程序 - >因为我无法知道下载的“正常”持续时间,所以当我开始执行任务时,我无法将其提供给执行程序,而且,当我接收数据时,必须重置计时器。
我在许多论坛上阅读了很多关于它的内容,并没有找到任何似乎适应的解决方案并且在这种情况下工作。如果有人知道另一种方法吗?
这是我正在执行的操作的代码:
public double get(String fileName) {
[...]
org.apache.commons.net.io.Util.copyStream(stO,stD,client.getBufferSize(),
this.localSize,
new org.apache.commons.net.io.CopyStreamAdapter() {
public void bytesTransferred(long totalBytesTransferred,
int bytesTransferred,long streamSize) {
setProgressDL(totalBytesTransferred);
//reset the timer here
}
});
[...]
}
以下是我测试的一些代码,启动了我的客户端:
public class TestFtp extends Thread {
[...]
public void run() {
System.out.println("Launching FTP test");
FtpClient client = new FtpClient(this.model, this, this.model.getFtpServer());
try {
//Attempting connection on the server
client.connect();
try {
// Attempting login
client.login(this.model.getUsername(), this.model.getPassword());
do {
client.changeDirectory("get");
// start timer
client.get(this.model.getDistantFileName());
// stop timer
client.changeToParentDirectory();
client.changeDirectory("put");
client.set(this.model.getDistantFileName(),
this.model.getNewFileName());
client.changeToParentDirectory();
try {
// Little pause between each test
Thread.sleep(500);
} catch (InterruptedException e) {}
// Continue test until the user stops it
} while (this.continuous);
// Once the test is over, logout
client.logout();
} catch (FTPLoginException e) {
// If login fails, the test ends
System.out.println("Unable to login to the server.");
}
} catch (FTPConnectException e) {
// If connection error, the test ends
System.out.println("Unable to connect to the server.");
}
}
如果有人可以提供帮助,请提前感谢您,如果您需要有关我的实际代码的更多信息,我可以在此处添加更多信息。
答案 0 :(得分:0)
嗯,我很抱歉,但我承认我没有读过您的所有代码,但是如果您想要中断正在运行的线程,请做两件事:
示例:
public void run() {
try {
// code to run
} catch (InterruptedException ie) {
// thread interrupted, may want to do some clean up
// but must return as quickly as possible to avoid halting external code
}
}
示例:
thread.interrupt();
这将告诉VM在你的线程中抛出InterruptedException,无论它在做什么,让你有机会做一些事情。
我希望这就是你要找的......
修改
好的,一个有效的具体例子:
public class Driver {
private static int count = 0;
public static void main(String[] args) {
Thread t = new Thread(new Runnable() {
@Override
public void run() {
try {
bigTask();
} catch (InterruptedException ie) {
System.out.println("Interrupted thread! Count is " + count);
}
}
});
t.start();
try {
Thread.sleep(1000);
System.out.println("Trying to interrupt thread");
t.interrupt();
} catch (InterruptedException e) {}
}
private static void bigTask() throws InterruptedException {
List<BigDecimal> bigs = new ArrayList<BigDecimal>();
for (int i = 0; i < 10000000; i++) {
bigs.add(BigDecimal.valueOf(i));
if (Thread.interrupted()) {
throw new InterruptedException();
}
count = i;
}
System.out.println("Ok, added ten million items, count is " + count);
}
}
答案 1 :(得分:0)
如果你不想抛出不必要的异常,你应该使用一个布尔标志来控制线程的执行(或runnable):
public class TestFtp extends Thread {
[...]
boolean abort;
public void run() {
[...]
do{
[...]
} while (this.continuous && !abort);
if (abort){
// You might want to do something here
}else{
// The stuff you normally do
}
}
}
然后只需从外部将abort
标记设置为false
即可。
通过这种方式,您可以更好地控制线程终止的方式,因为thread.interrupt();
将具有未定义的行为。