账号密码登录
微信安全登录
微信扫描二维码登录

登录后绑定QQ、微信即可实现信息互通

手机验证码登录
找回密码返回
邮箱找回 手机找回
注册账号返回
其他登录方式
分享
  • 收藏
    X
    《Java并发编程实战》使用newTaskFor实现线程取消的疑惑
    33
    0

    问题描述

    在《Java并发编程实战》第7章,作者通过newTaskFor方法封装实现了线程的取消。给出的demo如下:

    public abstract class SocketUsingTask <T> implements CancellableTask<T> {
        @GuardedBy("this") private Socket socket;
    
        protected synchronized void setSocket(Socket s) {
            socket = s;
        }
    
        public synchronized void cancel() {
            try {
                if (socket != null)
                    socket.close();
            } catch (IOException ignored) {
            }
        }
    
        public RunnableFuture<T> newTask() {
            return new FutureTask<T>(this) {
                public boolean cancel(boolean mayInterruptIfRunning) {
                    try {
                        SocketUsingTask.this.cancel();
                    } finally {
                        return super.cancel(mayInterruptIfRunning);
                    }
                }
            };
        }
    }
    
    
    interface CancellableTask <T> extends Callable<T> {
        void cancel();
    
        RunnableFuture<T> newTask();
    }
    
    
    @ThreadSafe
    class CancellingExecutor extends ThreadPoolExecutor {
        public CancellingExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue) {
            super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue);
        }
    
        public CancellingExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory) {
            super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory);
        }
    
        public CancellingExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, RejectedExecutionHandler handler) {
            super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, handler);
        }
    
        public CancellingExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) {
            super(corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue, threadFactory, handler);
        }
    
        protected <T> RunnableFuture<T> newTaskFor(Callable<T> callable) {
            if (callable instanceof CancellableTask)
                return ((CancellableTask<T>) callable).newTask();
            else
                return super.newTaskFor(callable);
        }
    }

    我觉得这段代码有点绕,感觉很不直白,我个人感觉可以换一种方法实现:

    public abstract class SocketUsingTask<T> extends FutureTask<T> implements Callable<T> {
        @GuardedBy("this") private Socket socket;
        
        protected synchronized void setSocket(Socket s) { socket = s; }
        
        public synchronized void cancel() {
            try {
                if (socket != null)
                    socket.close();
            } catch (IOException ignored) { }
        }
    
        @Override
        public boolean cancel(boolean mayInterruptIfRunning) {
            try {
                cancel();
            } finally {
                return super.cancel(mayInterruptIfRunning);
            }
        }
    }

    我想知道《Java并发编程实战》中给出的这个demo的最大的优点在哪?为什么要这样实现?因为感觉存在一些多余的操作。谢谢

    0
    打赏
    收藏
    点击回答
        全部回答
    • 0
    • 在Java并发编程中,线程的取消通常通过调用Thread类的interrupt()方法来实现。然而,如果在newTaskFor中直接调用Thread的interrupt()方法,可能会导致线程无法被中断,因为Thread类的interrupt()方法只在当前线程的中断上下文中可用。

      为了避免这种情况,你可以使用Thread类的join()方法来等待当前线程结束。join()方法会阻塞当前线程,直到目标线程完成其工作。

      以下是使用newTaskFor和join()方法实现线程取消的示例:

      ```java public class Main { public static void main(String[] args) { Thread thread1 = new Thread(new Task("Task 1")); Thread thread2 = new Thread(new Task("Task 2"));

          thread1.start();
          thread2.start();
      
          thread1.join();
          thread2.join();
      
          System.out.println("Thread 1 has completed");
          System.out.println("Thread 2 has completed");
      }
      

      }

      class Task implements Runnable { private String name;

      public Task(String name) {
          this.name = name;
      }
      
      @Override
      public void run() {
          System.out.println(name + " is running");
          try {
              Thread.sleep(2000);
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
          System.out.println(name + " is done");
      }
      

      } ```

      在这个示例中,我们首先创建了两个新的Thread对象,然后开始它们。然后我们调用thread1.join()和thread2.join()来等待它们完成。最后,我们打印出每个任务的名称,以确认它们是否都已经完成。

    更多回答
    扫一扫访问手机版
    • 回到顶部
    • 回到顶部