如何关掉一个线程

一、Thread.stop()

此方法已经过时,不推荐了。。。

因为它本质上是不安全的。停止线程会导致它解锁所有已锁定的监视器。(当ThreadDeath异常在堆栈中传播时,监视器被解锁。)如果之前由这些监视器保护的对象中的任何一个处于不一致状态,则其他线程现在可以以不一致的状态查看这些对象。据称这些物体被 损坏。当线程操作受损对象时,可能导致任意行为。就好比电脑的冷关机,或者突然断电。没有做任务的保护措施!可能会让你丢失数据。。。所以称之为不安全的!

public class Test {
    private int lock = 1;
    public void volatileTest() {
        Runnable runnable1 = new Runnable() {
            @Override
            public void run() {
                int n = 0;
                while (lock == 1){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("T1--"+ n++ +":runnable is running...");
                }
                System.out.println("T1--"+ n+":runnable is run out...");
            }
        };
        Runnable runnable2 = new Runnable() {
            @Override
            public void run() {
                int n = 0;
                while (lock == 1){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("T2--"+ n++ +":runnable is running...");
                }
                System.out.println("T2--"+ n+":runnable is run out...");
            }
        };
        Thread t1 =  new Thread(runnable1);
        Thread t2 =  new Thread(runnable2);
        t1.start();
        t2.start();
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t1.stop();  //你再键入这个方法时候,IDE会提醒你这个方法现在已经过时,不推荐了!

    }
}

二、利用volatile的可见性作为开关控制器

详见另一篇文章的描述:https://my.oschina.net/u/3697586/blog/3007720

三、Thread.interrupt()/isInterrupted/interrupted配合的信号。使得线程被中断抛出异常!

1)RUNNING状态线程—>先被阻塞成BLOCKED->再被中断—>flag=true!

2) RUNNING状态线程—>先被中断—>flag = true—>若再被阻塞—>flag = false!

3)interrupted()方法先返回当前的状态flag(不管是true还是false),同时又把标志位清除为false(不管之前是true还是false)

4)isInterrupted()方法只是返回当前的flag状态,不做任务赋值处理!

5)interrupted和isInterrupted的最大区别在于他们的源码定义中,一个传入清除参数为true,另一个传入为false!

 

 

 

 

其实Thread.interrupt功能意图是让阻塞BLOCKED的线程被中断掉

isInterrupted()源码,其中false表示不清楚标志位!

public boolean isInterrupted() {
    return isInterrupted(false);
}

要中断一个Java线程,可调用线程类(Thread)对象的实例方法:interrupte();然而interrupte()方法并不会立即执行中断操作;具体而言,这个方法只会给线程设置一个为true的中断标志(中断标志只是一个布尔类型的变量),而设置之后,则根据线程当前的状态进行不同的后续操作。如果,线程的当前状态处于非阻塞状态,那么仅仅是线程的中断标志被修改为true而已;如果线程的当前状态处于阻塞状态,那么在将中断标志设置为true后,还会有如下三种情况之一的操作:

  • 如果是wait、sleep以及jion三个方法引起的阻塞,那么会将线程的中断标志重新设置为false,并抛出一个InterruptedException;
  • 如果是java.nio.channels.InterruptibleChannel进行的io操作引起的阻塞,则会对线程抛出一个ClosedByInterruptedException;(待验证)
  • 如果是轮询(java.nio.channels.Selectors)引起的线程阻塞,则立即返回,不会抛出异常。(待验证)

    如果在中断时,线程正处于非阻塞状态,则将中断标志修改为true,而在此基础上,一旦进入阻塞状态,则按照阻塞状态的情况来进行处理;例如,一个线程在运行状态中,其中断标志被设置为true,则此后,一旦线程调用了wait、jion、sleep方法中的一种,立马抛出一个InterruptedException,且中断标志被清除,重新设置为false。

如果非阻塞---标志位置为true

如果阻塞-----标志位也置为true,然后还会继续分好多情况!如果是sleep引起的阻塞方式,则标志位重新清除为false!

如果这时候调用了interrupted函数,第一次返回true之后,再将标志位置为false!!然后第二第三次都是...false!

isInterrupted【外】]=false
thread.interrupt()....中断==当前线程状态==BLOCKED
isInterrupted【外】=true
interrupted【外】=false
interrupted【外】=false
执行线程体...
interrupted【内前】=true
进入睡眠...=RUNNABLE
结束线程...
interrupted【内后】=false
isInterrupted【外】]=false
thread.interrupt()....中断==当前线程状态==RUNNABLE
isInterrupted【外】=true
interrupted【外】=false
interrupted【外】=false
interrupted【内前】执行时,还没被打断=true
执行线程体...
进入睡眠...=RUNNABLE
结束线程...
interrupted【内后】=false

 

转载于:https://my.oschina.net/u/3697586/blog/3007749

<think>我们正在讨论LVGL(Light and Versatile Graphics Library)中如何关闭一个线程。首先需要明确:LVGL本身是一个线程设计的图形库,其主循环通常在一个线程中运行。但用户可能会创建额外的线程来处理其他任务(如网络通信、文件读取等),并在需要时关闭这些线程。 根据LVGL的设计原则,它不直接管理多线程。因此,关闭线程的方法实际上取决于你使用的操作系统和线程库(如pthread, FreeRTOS等)。下面分两种情况讨论: 1. **在裸机或RTOS环境中**:通常使用RTOS提供的线程删除函数。例如,在FreeRTOS中,可以使用`vTaskDelete()`函数。 2. **在Linux等操作系统环境中**:可以使用POSIX线程的`pthread_cancel()`或让线程自然退出。 然而,直接强制终止线程可能会导致资源泄漏(如未释放的内存、未关闭的文件描述符等)或LVGL状态不一致。因此,推荐的做法是使用一个标志位通知线程退出,然后等待线程自然结束。 以下是一个使用POSIX线程的示例: 步骤1:定义一个线程退出标志 步骤2:线程函数内部定期检查该标志,当标志被置位时,线程函数清理资源并退出 步骤3:主线程设置退出标志,并调用`pthread_join()`等待线程结束 示例代码: ```c #include <pthread.h> // 全局退出标志 volatile int thread_exit_flag = 0; // 线程函数 void* my_thread_func(void* arg) { while (!thread_exit_flag) { // 执行线程任务 // 注意:在任务中应避免长时间阻塞,以便及时检查退出标志 } // 清理资源 pthread_exit(NULL); } // 创建线程 pthread_t thread_id; pthread_create(&thread_id, NULL, my_thread_func, NULL); // 当需要关闭线程thread_exit_flag = 1; // 设置退出标志 pthread_join(thread_id, NULL); // 等待线程结束 ``` 在LVGL中,如果这个线程涉及到LVGL对象操作,需要注意:LVGL不是线程安全的。因此,在关闭线程时,需要确保没有线程正在操作LVGL对象。通常建议通过LVGL的任务机制(`lv_timer_create()`)来在主循环中执行与LVGL相关的操作。 另外,如果线程中执行的任务是周期性的,并且不需要并行处理,那么可以考虑使用LVGL的定时器(timer)代替线程。定时器由LVGL主循环调用,可以安全地操作LVGL对象,并且不需要手动关闭,通过`lv_timer_del(timer)`即可删除定时器。 总结:关闭线程的方法取决于具体环境,但推荐使用标志位通知线程退出,然后等待线程结束。在LVGL中,应尽量避免多线程直接操作LVGL对象,而使用定时器在主线中执行相关操作。 相关问题: 1. 如何在LVGL中使用定时器代替线程? 2. LVGL多线程操作时需要注意什么? 3. 在FreeRTOS中如何安全地关闭一个线程?</think>### 在LVGL中关闭线程的方法 在LVGL(Light and Versatile Graphics Library)中关闭线程需要谨慎处理,因为LVGL本身是单线程设计的图形库,不直接提供线程管理功能。以下是两种推荐方法: #### 方法1:使用线程退出标志(推荐) ```c // 全局退出标志 volatile bool thread_exit_flag = false; // 线程函数 void* your_thread_func(void* arg) { while(!thread_exit_flag) { // 执行线程任务... usleep(10000); // 10ms延迟 } return NULL; } // 关闭线程时设置标志 void close_thread() { thread_exit_flag = true; // 可选:等待线程退出 } ``` #### 方法2:使用操作系统API(台相关) ```c // POSIX线程示例 #include <pthread.h> pthread_t thread_id; // 创建线程 pthread_create(&thread_id, NULL, your_thread_func, NULL); // 关闭线程 void close_thread() { pthread_cancel(thread_id); // 发送取消请求 pthread_join(thread_id, NULL); // 等待线程结束 } ``` #### 重要注意事项: 1. **资源清理**:线程退出前必须释放所有资源(内存、文件句柄等) 2. **LVGL线程安全**:所有LVGL API调用必须在主线程执行[^5] 3. **同步机制**:使用互斥锁保护共享资源: ```c pthread_mutex_t lvgl_mutex = PTHREAD_MUTEX_INITIALIZER; void thread_safe_lvgl_call() { pthread_mutex_lock(&lvgl_mutex); lv_label_set_text(label, "Safe update"); pthread_mutex_unlock(&lvgl_mutex); } ``` 4. **替代方案**:优先使用LVGL内置定时器(`lv_timer_t`)替代线程: ```c lv_timer_t* timer = lv_timer_create(timer_cb, 100, NULL); // 100ms周期 // 删除定时器 lv_timer_del(timer); ``` [^1]: 强制终止线程可能导致资源泄漏和状态不一致 [^5]: LVGL对象操作必须在创建LVGL的主线程执行
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值