一、优雅的停止线程

开启线程的方式是:调用Thread中的start()方法,停止线程的方式:原本Thread提供了stop()方法,但是在JDK1.2坂本后就已经被禁用了。除了stop(),还有几个方法被禁用

    例如:

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

    2.销毁多线程:public void destory();

    3.挂起线程:public final void suspend();

    4.恢复挂起的线程执行public final void resume();

这些方法被禁用的原因是因为:可能会导致死锁。

范例:实现线程优雅的停止



public class ThreadDemo3 {
    public static boolean flag = true;
    public static void main(String[] args) throws  Exception{

        new Thread(()->{
            long m = 0;
           while (flag){
               try {
                   Thread.sleep(50);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               System.out.println(Thread.currentThread().getName()+" The  number is "+m++);
           }
        },"执行线程").start();
        Thread.sleep(200);
        flag=false;
    }
}



二、后台守护线程

充当保镖的角色,在多线程里面可以进行守护线程的定义,也就是说如果现在主线程的程序或其他线程在执行的时候,守护线程将一直存在。

    1.设置为守护线程:public final void setDaemon(boolean on);

    2.是否为守护线程:public final boolean isDaem();

范例:守护线程的使用



public class ThreadDemo4 {
    public static void main(String[] args) throws  Exception {
        Thread userThread = new Thread(()->{
           for(int i = 0; i< 10; i++){
               try {
                   Thread.sleep(100);
               } catch (InterruptedException e) {
                   e.printStackTrace();
               }
               System.out.println(Thread.currentThread().getName()+"num = "+i);
           }
        },"用户线程");
        Thread daemonThread = new Thread(()->{
            for(int i = 0; i< Integer.MAX_VALUE; i++){
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+"num = "+i);
            }
        },"守护线程");
        daemonThread.setDaemon(true);
        userThread.start();
        daemonThread.start();

    }
}



运行结果:

JAVA线程启动销毁 java多线程销毁_守护线程

可以发现所有的守护线程都是围绕在用户线程的周围,如果程序执行完毕,守护线程也就没有存在的必要了,最大的守护线程就是GC线程。

三、volatile关键字

在多线程的定义中,volatile关键字主要是在属性定义上使用的,表示此属性为直接数据操作,而不进行副本的拷贝处理。

在我们正常进行变量处理的时候往往会经历如下几个步骤:

    1.获取变量原有的数据内容副本;

    2.利用副本为变量进行数学计算;

    3.将计算后的变量,保存到原始空间之中;

而如果一个属性追加了volatile关键字,表示的就是不使用副本,而是直接操作原始变量。

JAVA线程启动销毁 java多线程销毁_java_02

范例:valatile的正确使用



class MyThread implements Runnable{
    public  volatile  int ticket = 5;
    @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 = " + ticket--);
            }
        }
    }
}
public class Main {
    public static void main(String[] args) {
        MyThread mt = new MyThread();
        new Thread(mt,"票贩A").start();
        new Thread(mt,"票贩B").start();
        new Thread(mt,"票贩C").start();

    }
}



面试题:请解释volatile与synchronized的区别?

    1.volatile主要是属性上使用,而synchronized是在代码块和方法上使用的;

    2.volatile无法描述同步的处理,他只是一种直接内存的处理,避免了副本的操作;