14.6 优雅地停止线程

在Java中,一个线程对象是有自己的生命周期的,如果想要控制好线程的生命周期,则首先应该认识其生命周期,如图。

 

        从图中可以发现,大部分线程生命周期的方法都已经学过了,那么这里主要介绍下面3种新方法。

                1.停止多线程:public void stop()。

                2.挂起线程:public final void suspend()、暂停执行。

                3.恢复挂起的线程执行:public final void resume()。

        但这3种方法会产生死锁问题,所以从JDK1.2开始已经不推荐使用。那么如何停止一个线程的执行呢?可以通过标志位的方式停止。

范例:优雅地停止线程运行        

package cn.kuiba.util;

public class Main{
    public static boolean flag=true;                        //线程停止标记
    public static void main(String[] args)throws Exception{
        new Thread(()->{                                    //新的线程对象
            long num=0;
            while (flag){                                   //判断标记
                try {
                    Thread.sleep(50);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"正在运行、num="+num++);
            }
        },"执行线程").start();
        Thread.sleep(200);                            //运行200毫秒
        flag=false;                                         //停止线程,修改执行标记
    }
}

        本程序为了可以停止线程运行,所以专门定义了flag属性,随后利用对flag属性内容的修改实现了停止线程执行的目的。

提示:线程的完整运行状态

 14.7 后台守护线程

        Java中的线程分为两类:用户线程和守护线程。守护线程(Daemon)是一种运行在后台的线程服务线程,当用户线程存在时,守护线程也可以同时存在;当用户线程全部消失时,守护线程也会消失。

        Java中的线程都是通过Thread类来创建的,用户线程和守护线程处理运行模式的区别外,其他完全相同。通过如表所示的方法进行守护线程操作。

 范例:使用守护线程

package cn.kuiba.util;

public class Main{
    public static void main(String[] args)throws Exception{
        Thread userThread = new Thread(()->{
            for (int x=0;x<2;x++){
                try {
                    Thread.sleep(100);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"正在运行、x="+x);
            }
        },"用户线程");                                               //完成核心的业务
        Thread daemonThread =new Thread(()->{
            for (int x=0;x<Integer.MAX_VALUE;x++){
                try {
                    Thread.sleep(100);
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"正在运行、x="+x);
            }
        },"守护线程");                                              //完成核心的业务
        daemonThread.setDaemon(true);                                    //设置成守护线程
        userThread.start();                                             //启动用户线程
        daemonThread.start();                                           //启动守护线程
    }
}



程序执行结果:
守护线程正在运行、x=0
用户线程正在运行、x=0
用户线程正在运行、x=1
守护线程正在运行、x=1

        本程序定义了一个守护线程,并且该守护线程将一直进行信息的输出,但是通过执行的结果可以发现,当用户线程消失后守护线程也同时结束。

14.8 volatile关键字

        在多线程编程中,若干个线程为了可以实现公共资源的操作,往往是复制相应变量的副本,待操作完成后再将此副本变量数据与原始变量进行同步处理。如果想要直接进行原始变量的操作,节约复制变量副本与同步的时间的话,则可以再变量声明时使用volatile关键字。

范例:使用volatile关键字定义变量

package cn.kuiba.util;

class MyThread implements Runnable{
    private volatile int ticket=3;              //直接内存操作
    @Override
    public void run(){
        synchronized (this){                    //同步处理
            while (this.ticket>0){
                try {
                    Thread.sleep(100);    //模拟延迟
                }catch (InterruptedException e){
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"卖票处理,ticket="+this.ticket--);
            }
        }
    }
}
public class Main{
    public static void main(String[] args)throws Exception{
        MyThread mt =new MyThread();
        new Thread(mt,"售票员A").start();
        new Thread(mt,"售票员B").start();
        new Thread(mt,"售票员C").start();
    }
}



程序执行结果:
售票员A卖票处理,ticket=3
售票员A卖票处理,ticket=2
售票员A卖票处理,ticket=1

        本程序在定义ticket属性时使用了volatile关键字进行定义,这样就表示该变量在进行操作时将直接会进行原始变量内容的处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值