Logo

郎哥编程

线程的休眠、中断和加入

2021-07-14 300

学习目标:掌握线程的休眠、中断、加入等操作方法。

线程的休眠

线程的休眠就是把当前正在运行的线程挂起一段时间(时间值由参数传入),挂起时间到期后,JVM会在适当的时间再次唤醒该线程。

Thread类的sleep()方法可以让当前线程休眠,sleep()方法说明如下:

sleep (long millis) throws InterruptedException

该方法用于在指定的millis毫秒内让当前正在执行的线程休眠(暂停执行),该方法的执行可能会抛出InterruptedException异常,因此需要将sleep()方法的调用放在try-catch块中。

案例3:建立ThreadSleep类,并在run()方法中编写线程功能代码。

在thread包下新建ThreadSleep类。代码如下:

package thread;
 
public class ThreadSleep extends Thread {
    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();
        for (int i = 0; i < 100; i++) {
            System.out.println("MyRunner:" + i);
            try {
                System.out.println(Thread.currentThread().getName() + "休眠0.5秒!");
                //自身线程挂起500毫秒
                Thread.sleep(500);
            } catch (InterruptedException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        }
 
    }
}

ThreadSleep类在每次循环都会调用Thread类的sleep方法将自身线程挂起500毫秒,然后再继续执行。

在thread包下新建ThreadSleepTest测试类,启动ThreadSleep线程。代码如下:

package thread;
 
public class ThreadSleepTest {
    public static void main(String[] args) {
        // 实例化MyThread对象
        ThreadSleep  thread = new ThreadSleep();
        // 调用Thread类的strat()方法启动线程
        thread.start();
 
        try {
            //主线程挂起1000毫秒
            System.out.println(Thread.currentThread().getName()+ "休眠1秒!");
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
 
    }
}

在ThreadSleepTest类主线程启动子线程后,应用Thread类的sleep方法将主线程挂起1000毫秒,因为sleep方法抛出InterruptedException异常,因此调用sleep方法时,需要包含在try-cahtch语句,用于捕获sleep方法可能抛出的异常。

程序执行结果如下图所示:

04.png

线程的中断

线程的中断不是停止线程的运行,而是在线程中设置中断状态,被中断的线程需要响应和处理中断状态。

Thread类定义了三个与中断相关的方法,分别说明如下:

●   void  interrupt()

该方法用于中断当前线程,设置当前线程为中断状态。

●   boolean  interrupted()

该方法用于判断当前线程是否处于中断状态,如果处于中断状态返回true,并清除线程的中断状态标记。

●   boolean  interrupted()

该方法用于判断当前线程是否处于中断状态,如果处于中断状态返回true,该方法不会清除线程的中断状态标记。

案例4:建立ThreadInterrup类,并在run()方法中编写线程功能代码。

在thread包下新建ThreadInterrup类。代码如下:

package thread;
 
public class ThreadInterrup extends Thread{
    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();
        for( int i = 0; i<100; i++ ) {
            // 响应中断
            if (Thread.currentThread().isInterrupted()) {
                System.out.println("ThreadInterrup线程被中断,程序退出。");
                return;
            }
            System.out.println("ThreadInterrup:" + i);
        }
 
    }
 
}

ThreadInterrup类对线程的中断状态进行了响应处理,在for循环中调用Thread类的isInterrupted()方法判断线程是否处于中断状态,如果被设置为中断状态则退出程序。

在thread包下新建ThreadInterrupTest测试类,启动ThreadInterrup线程,并调用interrupt()方法中断线程。代码如下:

package thread;



public class ThreadInterrupTest {

    public static void main(String[] args) {

        // 实例化MyThread对象

        ThreadInterrup  thread = new ThreadInterrup();

        // 调用Thread类的strat()方法启动线程

        thread.start();

        // 中断当前线程

        thread.interrupt();



    }

}

在ThreadInterrupTest类主线程启动子线程后,应用Thread类的interrupt()方法中断子线程,因为子线程内部对线程中断状态进行了响应处理,因此子线程结束运行。

程序执行结果如下图所示:

06.png

当线程内部不响应中断状态时,调用Thread类的interrupt()方法对线程没有任何影响。

线程的加入

线程的加入是指在当前线程中执行另外一个线程。例如A线程在执行过程中需要先执行B线程,等待B线程执行完毕后,A线程再继续执行。在这种情况下,就可以使用Thread类的join()方法来完成。

下面是Thread类线程加入相关的常用方法,分别说明如下:

●   void  join()

该方法用于将当前线程加入到另外一个线程,另外一个线程会等待该线程执行完毕再继续执行。

●   void  join(long millis)

该方法用于将当前线程加入到另外一个线程,另外一个线程会等待该线程执行millis毫秒后再执行,如果当前线程millis毫秒后没有结束,两个线程会并发执行。

案例5:建立ThreadA类和ThreadB类,在ThreadA类加入ThreadB类线程。

在thread包下新建ThreadA类。代码如下:

package thread;
 
public class ThreadA extends Thread{
    Thread  threadB = null;
 
    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();
        // 在线程中执行的代码
        for( int i = 0; i<100; i++ ) {
            if( i == 10)
            {
                // 调用threadB的join方法,执行threadB线程
                if( threadB != null )
                {
                    try {
                        threadB.start();
                        threadB.join();
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }
            System.out.println("ThreadA:" + i);
        }
    }
 
    public Thread getThreadB() {
        return threadB;
    }
 
   
    public void setThreadB(Thread threadB) {
        this.threadB = threadB;
    }
 
}

ThreadA类内部定义了Thread类型的变量,用于存储ThreadB的实例对象引用。在ThreadA类的run()方法调用启动ThreadB线程,并调用ThreadB的join()方法,等待ThreadB线程执行完毕。

在thread包下新建ThreadB类。代码如下:

package thread;
 
public class ThreadB extends Thread{
    @Override
    public void run() {
        // TODO Auto-generated method stub
        super.run();
        try {
            System.out.println("线程B启动");
            Thread.sleep(500);
            System.out.println("线程B结束");
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
 
}

ThreadB线程休眠500毫秒后结束。

在thread包下新建ThreadJoinTest类。代码如下:

package thread;
 
public class ThreadJoinTest {
    public static void main(String[] args) {
        ThreadA  threadA = new ThreadA();
        ThreadB  threadB = new ThreadB();
        threadA.setThreadB(threadB);
        threadA.start();
 
    }
}

ThreadJoinTest程序分别实例化ThreadA和ThreadB对象,调用ThreadA的setThreadB()方法设置ThreadA的threadB变量,并启动ThreadA线程。

代码在线纠错(通义千问 qwen-max)

支持粘贴多个代码文件,提交后由阿里云通义千问自动分析代码漏洞、语法错误、逻辑问题并给出修改建议。
您已解锁 AI 代码纠错功能,可正常使用!

评论区

登录 后发表评论
暂无评论