目录索引
优雅的停止线程
线程的启动使用的是Thread类的start()方法,而它还提供了 stop() 方法去停止线程、destroy() 方法去销毁线程、suspend() 方法去挂起线程暂停执行 以及 resume() 方法使挂起线程的恢复但现在都被废除了(因为这些方法可能导致死锁)
所以要想去停止线程可以通过flag去控制
public class ThreadDemo {
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 ; //停止线程
}
}
后台守护线程
当主线程或其他线程还在运行的时候守护线程将一直存在
在Thread类里面提供有如下的守护线程的操作方法:。
- 设置为守护线程: public final void setDaemon( boolean on);
- 判断是否为守护线程: public final boolean isDaemon( );
所有的守护线程都是围绕在用户线程的周围,如果程序执行完毕了,守护线程也就消失了,在整个JVM中最大的的守护线程就是GC线程。
程序执行中GC线程会一直存在,如果程序执行完毕,GC线程也消失
volatile关键字
在多线程的定义之中,volatile关键字主要是在属性定义上使用的,表示此属性为直接数据操作,而不进行副本的拷贝处理。这样的话在一些书上就将其错误的理解为同步属性了。
在正常进行变量处理的时候往往会经历如下的几个步骤:
- 获取变量原有的数据内容副本;
- 利用副本为变量进行数学计算;
- 将计算后的变量,保存到原始空间之中;
而如果一个属性_上追加了volatile 关键字,表示的就是不使用副本,而是直接操作原始变量,相当于节约了:拷贝副本、重新保存的步骤
class MyThread implements Runnable {
private volatile int ticket = 5;// 直接内存操作
@Override
public void run() {
synchronized (this) {
//同步代码块
while (this.ticket > 0) {
System.out.println(Thread.currentThread().getName()+"卖票处理,ticket="+this.ticke--);
}
}
}
}
public class ThreadDemo {
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();
}
}
面试题:请解释volatile与synshronized的区别?
- volatile 主要在属性上使用,而synchronized是在代码块与方法上使用的;。
- volatile无法描述同步的处理,它只是一种直接内存的处理,避免了副本的操作,而synchronized是实现同步的;