线程的取消和关闭

1. 线程中断

1.1 线程睡眠被打断

class ThreadSleep implements Runnable {
    @Override
    public void run() {
        try {
            System.out.println("睡眠前当前线程状态" + Thread.currentThread().isInterrupted());
              while (true) {
                Thread.sleep(1000);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }finally {
            System.out.println("当前线程状态" + Thread.currentThread().isInterrupted());
        }
    }
}

        ThreadSleep threadSleep = new ThreadSleep();
        Thread thread1 = new Thread(threadSleep);
        thread1.start();
        Thread.sleep(100);
        thread1.interrupt();

在这里插入图片描述

1.2 线程运行被打断

class ThreadRun implements Runnable {
    @Override
    public void run() {
        System.out.println("运行前线程状态" + Thread.currentThread().isInterrupted());
        try {
            while (true) {
                Thread current = Thread.currentThread();
                boolean interrupted = current.isInterrupted();
                if(interrupted) {
                    System.out.println("当前线程状态" + interrupted);
                    break;
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

   ThreadRun threadRun=new ThreadRun();
        Thread thread1 = new Thread(threadRun);
        thread1.start();
        Thread.sleep(100);
        thread1.interrupt();

在这里插入图片描述
由上可见:
对于处于睡眠状态的线程由外部打断会报出InterruptedException异常,且中断标识位为false标识为未被打断
对于正常运行的线程由外部打断不会报出异常,且中断标识为被修改成true,代表以及被打断

其次:

我们在以上两个类里面添加:

   public void interruptBySelf(){
        Thread.interrupted();
    }

再来运行:

  ThreadRun threadRun=new ThreadRun();
        Thread thread1 = new Thread(threadRun);
        thread1.start();
        Thread.sleep(100);
        // 这里改为自己打断
        threadRun.interruptBySelf();

在这里插入图片描述

可见,由于状态位未改变一直处于运行状态

再来试试睡眠状态:


      ThreadSleep threadSleep=new ThreadSleep();
        Thread thread1 = new Thread(threadSleep);
        thread1.start();
        Thread.sleep(100);
        //
        threadSleep.interruptBySelf();

在这里插入图片描述

测试当前线程是否被中断的
* 通过这个方法可以清除线程的中断状态
在换句话说,如果这个方法被连续调用两次,则
*第二次调用将返回false(除非当前线程为false)
*在第一个呼叫清除其中断后,再次中断
在第二次通话之前)。
一个线程的中断被忽略,因为一个线程不是活的
*在中断的时候会通过这个方法反映出来
*返回falsepublic static boolean interrupted() {
        return currentThread().isInterrupted(true);
    }

Java并发编程实战提出:
调用interrupt并不意味着停止目标线程正在执行的工作;它仅仅传递了请求中断的消息;
对中断最好的理解就是:
仅仅会发出中断请求,线程自己会在下一个方便的时刻中断;
中断是实现取消最明智的选择;

于是我们有了以下取消方法:

1.3 二阶段终止(关闭)

在一个线程 T1 中如何“优雅”终止线程 T2?
错误思路:

  • 使用线程对象的 stop() 方法停止线程
    stop 方法会真正杀死线程,如果这时线程锁住了共享资源,那么当它被杀死后就再也没有机会释放锁,其它线程将永远无法获取锁
  • 使用 System.exit(int) 方法停止线程
    目的仅是停止一个线程,但这种做法会让整个程序都停止

正确思路:

在这里插入图片描述

class TPTInterrupt {
    private Thread thread;

    public void start() {
        thread = new Thread(() -> {
            while (true) {
                Thread current = Thread.currentThread();
                if (current.isInterrupted()) {
                    System.out.println("准备结束");
                    break;
                }
                try {
                    Thread.sleep(1000);
                    System.out.println("运行运行....");
                } catch (InterruptedException e) {
                    current.interrupt();
                }
                // 执行监控操作
            }
        }, "监控线程");
        thread.start();
    }

    public void stop() {
        thread.interrupt();
    }
}

        TPTInterrupt interrupt = new TPTInterrupt();
        interrupt.start();
        Thread.sleep(2000);
        interrupt.stop();

在这里插入图片描述

2. 线程取消

2.1 Volatile取消(关闭线程)

class Cancel implements Runnable {
    private volatile boolean cancelled;

    @Override
    public void run() {
        System.out.println("任务正在执行...");
        while (!cancelled) {

        }
        System.out.println("任务取消...");
    }

    public void cancel() {
        this.cancelled = true;
    }
}

  private static void cancel() throws InterruptedException {
        Cancel cancel = new Cancel();
        new Thread(cancel).start();
        Thread.sleep(1000);
        cancel.cancel();
    }

2.2 Future 取消

cancel:参数mayInterruptedIfRunning,当mayInterruptedIfRunning为true,并且当前任务正在运行,那么这个线程应该中断的,如果是false意味着如果任务没有启动,不要运行这个任务;

 ExecutorService executor = Executors.newSingleThreadExecutor();
        Future future = executor.submit(new ThreadRun());
        Thread.sleep(100);
        future.cancel(true);

注意一般要交给线程池来使用Future来取消比较好

在 C 语言中,并没有直接提供内置的线程库像 Java 或 Python 那样可以方便地取消或停止线程。如果你使用的是 POSIX 线程(pthread),通常的做法是通过调用 `pthread_cancel` 函数尝试中断线程,但是这个操作并不总是保证成功,因为线程可能会因为各种原因进入不可中断的状态。 下面是一个简单的例子,展示如何尝试取消一个已创建的线程: ```c #include <pthread.h> void *thread_function(void *arg) { // 这里是线程执行的代码 while (1); // 永远循环,模拟无法立即停止的任务 } int main() { pthread_t thread_id; int ret; // 创建线程 if ((ret = pthread_create(&thread_id, NULL, thread_function, NULL)) != 0) { printf("Error creating thread: %d\n", ret); return 1; } // 尝试取消线程 pthread_attr_t attr; pthread_attr_init(&attr); pthread_attr_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &attr); if ((ret = pthread_cancel(thread_id)) == PTHREAD_CANCELED) { printf("Thread cancelled successfully.\n"); } else if (ret == ESRCH) { printf("Thread not found; already terminated.\n"); } else { printf("Error cancelling thread: %d\n", ret); } pthread_attr_destroy(&attr); // 清理其他资源 pthread_join(thread_id, NULL); return 0; } ``` 在这个示例中,如果线程还在运行并且能够被取消,`pthread_cancel` 会返回 `PTHREAD_CANCELED`,表示线程已经结束。如果线程不存在(比如它已经终止了),`ESRCH` 错误会被捕获。 需要注意的是,C 语言的线程控制不如现代高级语言那样直观,实际应用时需要考虑线程状态和同步等问题。如果需要更细粒度的控制,建议考虑使用更高级别的线程库或者操作系统提供的原生线程管理API。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值