Java 任务取消方法或事件

Java 任务取消方法或事件,java,networking,javafx,concurrency,Java,Networking,Javafx,Concurrency,我正在尝试创建一个网络javafx应用程序,并在任务中运行serverloop。因为ServerSocket accept方法正在阻塞,我无法测试任务是否已取消(使用isCancelled()) 我当前的实现: class ServerTask extends Task<Void> { ExecutorService executorService; final int PORT = 12345; @Override protected Void c

我正在尝试创建一个网络javafx应用程序,并在任务中运行serverloop。因为ServerSocket accept方法正在阻塞,我无法测试任务是否已取消(使用isCancelled())

我当前的实现:

class ServerTask extends Task<Void> {
    ExecutorService executorService;
    final int PORT = 12345;

    @Override
    protected Void call() throws Exception {
        executorService = Executors.newFixedThreadPool(8);

        try (ServerSocket serverSocket = new ServerSocket(PORT)) {
            while (true)
            {
                executorService.execute(
                        new Client(serverSocket.accept()));
            }
        }
        catch (IOException e) {
            System.out.print(e.getMessage());
        }

        return null;
    }
}
classservertask扩展了任务{
执行服务执行服务;
最终int端口=12345;
@凌驾
受保护的Void调用()引发异常{
executorService=Executors.newFixedThreadPool(8);
try(ServerSocket-ServerSocket=newserversocket(端口)){
while(true)
{
executorService.execute(
新客户端(serverSocket.accept());
}
}
捕获(IOE异常){
System.out.print(如getMessage());
}
返回null;
}
}

在任务中调用chancel时是否有可能覆盖或捕获事件,或者我在javafx应用程序中实现serverloop的方法是否错误?如果是这样,应该怎么做?

任务
将在调用
取消()
后立即转换为
取消
状态,即使
调用()
方法仍然被阻止运行不间断的方法

ServerSocket
可以通过关闭套接字有效地“中断”,这将导致当前被阻止的任何
accept()
方法以
IOException
终止

所以你可以这样做:

class ServerTask extends Task<Void> {
    ExecutorService executorService;
    final int PORT = 12345;

    private ServerSocket serverSocket ;

    @Override
    protected Void call() throws Exception {
        executorService = Executors.newFixedThreadPool(8);

        try (serverSocket = new ServerSocket(PORT)) {
            while (true)
            {
                executorService.execute(
                        new Client(serverSocket.accept()));
            }
        }
        catch (IOException e) {
            if (isCancelled()) {
                System.out.println("Cancelled");
            } else {
                System.out.print(e.getMessage());
            }
        }

        return null;
    }

    @Override
    protected void cancelled() {
        if (serverSocket != null) {
            try {
                serverSocket.close();
            } catch (IOException exc) {
                exc.printStackTrace();
            }
        }
    }
}
classservertask扩展了任务{
执行服务执行服务;
最终int端口=12345;
私有服务器套接字服务器套接字;
@凌驾
受保护的Void调用()引发异常{
executorService=Executors.newFixedThreadPool(8);
try(serverSocket=newserversocket(端口)){
while(true)
{
executorService.execute(
新客户端(serverSocket.accept());
}
}
捕获(IOE异常){
如果(isCancelled()){
系统输出打印项次(“取消”);
}否则{
System.out.print(如getMessage());
}
}
返回null;
}
@凌驾
受保护的作废已取消(){
if(serverSocket!=null){
试一试{
serverSocket.close();
}捕获(IOException){
exc.printStackTrace();
}
}
}
}
下面是一个非常快速完整的示例:

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;

import javafx.application.Application;
import javafx.concurrent.Task;
import javafx.geometry.Insets;
import javafx.geometry.Pos;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.layout.VBox;
import javafx.stage.Stage;

public class NonIterruptableTaskCancellation extends Application {

    @Override
    public void start(Stage primaryStage) throws Exception {

        ServerSocket socket = new ServerSocket(2048);

        Task<Void> task = new Task<Void>() {
            @Override
            protected Void call() throws Exception {

                while (! isCancelled()) {
                    try {
                        Socket s = socket.accept();
                        System.out.println("Connected to "+s);
                        s.close();
                    } catch (IOException exc) {
                        if (isCancelled()) {
                            System.out.println("Cancelled");
                        } else {
                            System.out.println("Unexpected IO Exception");
                            throw exc ;
                        }
                    }
                }

                return null ;
            }

            @Override
            protected void cancelled() {
                try {
                    socket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        };

        Thread t = new Thread(task);
        t.setDaemon(true);
        t.start();

        Label label = new Label();
        label.textProperty().bind(task.stateProperty().asString());

        Button cancel = new Button("Cancel");
        cancel.disableProperty().bind(task.runningProperty().not());
        cancel.setOnAction(e -> task.cancel());

        VBox root = new VBox(5, label, cancel);
        root.setPadding(new Insets(10));
        root.setAlignment(Pos.CENTER);

        Scene scene = new Scene(root, 200, 120);
        primaryStage.setScene(scene);
        primaryStage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
import java.io.IOException;
导入java.net.ServerSocket;
导入java.net.Socket;
导入javafx.application.application;
导入javafx.concurrent.Task;
导入javafx.geometry.Insets;
导入javafx.geometry.Pos;
导入javafx.scene.scene;
导入javafx.scene.control.Button;
导入javafx.scene.control.Label;
导入javafx.scene.layout.VBox;
导入javafx.stage.stage;
公共类非腐败任务取消扩展应用程序{
@凌驾
public void start(Stage primaryStage)引发异常{
ServerSocket=新的ServerSocket(2048);
任务=新任务(){
@凌驾
受保护的Void调用()引发异常{
而(!isCancelled()){
试一试{
sockets=Socket.accept();
System.out.println(“连接到”+s);
s、 close();
}捕获(IOException){
如果(isCancelled()){
系统输出打印项次(“取消”);
}否则{
System.out.println(“意外IO异常”);
抛出exc;
}
}
}
返回null;
}
@凌驾
受保护的作废已取消(){
试一试{
socket.close();
}捕获(IOE异常){
e、 printStackTrace();
}
}
};
线程t=新线程(任务);
t、 setDaemon(true);
t、 start();
标签=新标签();
label.textProperty().bind(task.stateProperty().asString());
按钮取消=新按钮(“取消”);
cancel.disableProperty().bind(task.runningProperty().not());
取消.setOnAction(e->task.cancel());
VBox根=新的VBox(5,标签,取消);
根。设置填充(新插图(10));
根部设置对齐(位置中心);
场景=新场景(根,200,120);
初级阶段。场景(场景);
primaryStage.show();
}
公共静态void main(字符串[]args){
发射(args);
}
}

你能发布一些代码来说明你在做什么吗?如果有帮助的话,关闭套接字可以(有效地)中断对
ServerSocket.accept()的调用。
是的,我知道,但我想通过解构器之类的东西来调用它。Java中没有解构器。我不太清楚你的意思。我考虑重写cancel方法,因为它只调用cancel(true),但我是JavaFX的新手,不想破坏某些东西。JavaFX相当不错(至少比Swing好),至少不应该重写它们。我认为这里正确的方法是重写,这是专门(明确)为重写而设计的。