如何正确的暂停线程

对于启动一个线程都知道如何启动,但是对于中断一个线程呢,例如在线程持续处理业务时,由于处理逻辑中有访问接口异常,在接口恢复后再对数据进行处理,以免出现大量错误数据,那么采用什么方式进行中断,需要谨慎的选择,Thread的api中提供了几个方式进行中断,stop()、suspend()都已经标记为过时,因为存在安全问题,再这里主要对两种中断方式做讲解。

方式说明
设置标志在线程中设置标志位来判断是否暂停
interrupt()中断线程,这时只是标记要中断,实际什么时间暂停将由计算机决定

设置标志方式

首先创建一个线程类并且声明volatile的Boolean的标志。

/**
 * @author : Erick
 * @version : 1.0
 * @Description :
 * @time :2019-4-19
 */
public class JmsThread implements Runnable {
	//volatile可见性,变量变更始终从主存中获取最新值,而不存在延迟。
    volatile Boolean keepRunning = true;

    @Override
    public void run() {
        while (true){
        	//判断标志是否为true
            if (keepRunning){
                System.out.println("当前运行线程为:" +Thread.currentThread().getName());
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

编写测试类

import java.util.HashMap;
import java.util.Map;

/**
 * @author : Erick
 * @version : 1.0
 * @Description :
 * @time :2019-4-19
 */
public class TestJms {
    static Map<Integer , Runnable> QueueMap = new HashMap<Integer, Runnable>();
    public static void main(String[] args) {
    	//开启10个线程运行
        for (int i = 0; i < 10; i++) {
            JmsThread jmsThread = new JmsThread();
            Thread thread = new Thread(jmsThread);
            thread.setName("线程名称:"+i);
            QueueMap.put(i,jmsThread);
            thread.start();
        }

		//让所有线程运行5s。
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
		//将每个线程中的标志都设置为false
        for (int i = 0; i < 9; i++) {
            JmsThread jmsThread = (JmsThread) QueueMap.get(i);
            jmsThread.keepRunning = false;
        }
        System.out.println("线程0-8已经暂停");

        try {
        	//运行10s
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
		//再将标志为置为true
        for (int i = 0; i < 9; i++) {
            JmsThread jmsThread = (JmsThread) QueueMap.get(i);
            jmsThread.keepRunning = true;
        }

        System.out.println("线程0-8已经启动");
    }
}

输出结果,开始的5s所有线程随机运行,等把前9个线程标志位更改为false后则只有一个线程9在运行,线程内有1s的等待,这里会输出10次,然后将标志位更改为true,又会将所有线程启动运行。

当前运行线程为:线程名称:1
当前运行线程为:线程名称:2
当前运行线程为:线程名称:3
当前运行线程为:线程名称:4
当前运行线程为:线程名称:5
当前运行线程为:线程名称:8
当前运行线程为:线程名称:7
当前运行线程为:线程名称:6
当前运行线程为:线程名称:9
当前运行线程为:线程名称:2
当前运行线程为:线程名称:1
当前运行线程为:线程名称:0
当前运行线程为:线程名称:3
当前运行线程为:线程名称:5
当前运行线程为:线程名称:4
当前运行线程为:线程名称:9
当前运行线程为:线程名称:6
当前运行线程为:线程名称:7
当前运行线程为:线程名称:8
线程0-8已经暂停
当前运行线程为:线程名称:9
当前运行线程为:线程名称:9
当前运行线程为:线程名称:9
当前运行线程为:线程名称:9
当前运行线程为:线程名称:9
当前运行线程为:线程名称:9
当前运行线程为:线程名称:9
当前运行线程为:线程名称:9
当前运行线程为:线程名称:9
当前运行线程为:线程名称:9
线程0-8已经启动
当前运行线程为:线程名称:0
当前运行线程为:线程名称:3
当前运行线程为:线程名称:1
当前运行线程为:线程名称:2
当前运行线程为:线程名称:9
当前运行线程为:线程名称:6
当前运行线程为:线程名称:8
当前运行线程为:线程名称:4
当前运行线程为:线程名称:5
当前运行线程为:线程名称:7
当前运行线程为:线程名称:1
当前运行线程为:线程名称:0
当前运行线程为:线程名称:3
当前运行线程为:线程名称:2
当前运行线程为:线程名称:9
当前运行线程为:线程名称:6
当前运行线程为:线程名称:7
当前运行线程为:线程名称:5
当前运行线程为:线程名称:8
当前运行线程为:线程名称:4
当前运行线程为:线程名称:1
当前运行线程为:线程名称:3
当前运行线程为:线程名称:0
当前运行线程为:线程名称:2
当前运行线程为:线程名称:9

使用interrupt()进行中断

/**
 * @author : Erick
 * @version : 1.0
 * @Description :
 * @time :2019-6-13
 */
public class InterruptTest {
    public static void main(String[] args) {
        Thread thread = new Thread(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i <100 ; i++) {
                    System.out.println(Thread.currentThread().getName());
                }
            }
        });
        thread.setName("aaaaa");
        thread.start();
        try {
            Thread.sleep(10);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        thread.interrupt();
        System.out.println("线程已经暂停");
    }
}

而结果呢,线程不会因为中断请求而中断线程本身的操作,还是会继续执行。

aaaaa
aaaaa
aaaaa
aaaaa
aaaaa
aaaaa
aaaaa
aaaaa
aaaaa
aaaaa
aaaaa
aaaaa
aaaaa
aaaaa
aaaaa
aaaaa
aaaaa
aaaaa
aaaaa
线程已经暂停
aaaaa
aaaaa
aaaaa
aaaaa

通过interrupt方式只是通知要中断线程,具体什么时间中断是靠机器本身来决定的。


在这里插入图片描述

Qt中的QThread类提供了一种在多线程应用程序中管理线程的方法。然而,在使用Qt的moveToThread()方法将一个QObject派生类对象移动到另一个线程时,并不能直接暂停线程。 moveToThread()方法实际上是将一个QObject对象的所有方法从一个线程中转移到另一个线程中执行。这样做的目的是为了在多线程应用程序中实现对象的跨线程调用,以避免线程间的竞争条件和死锁等问题。 如果需要暂停线程,可以通过其他方式来实现。例如,可以在QObject对象的方法中添加一个标志位,用来控制方法的执行。当需要暂停线程时,可以将该标志位设置为一个特定的值,使方法在执行前检查该标志位,如果值为暂停状态,就不执行。当需要恢复线程时,可以将该标志位设置为另一个值,使方法可以正常执行。 另外,也可以通过使用信号和槽机制来实现线程暂停和恢复。可以定义一个信号暂停线程,然后在槽函数中执行暂停操作;定义另一个信号恢复线程,然后在槽函数中执行恢复操作。通过发出这两个信号,可以控制线程暂停和恢复之间切换。 需要注意的是,在进行线程暂停和恢复的操作时,要确保线程的同步和安全。可以使用互斥锁或其他线程同步机制来保证多线程操作的正确性和可靠性。 综上所述,Qt的moveToThread()方法并不能直接用于暂停线程。但可以通过其他方式,如标志位或信号和槽机制,来实现线程暂停和恢复操作。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨香异境

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值