一. Thread与虚拟机栈
粗略地认为一个java进程的内存大小为:堆内存+线程数*栈内存。因此线程数量与栈内存的大小是反比关系。
二.守护线程
JVM程序在没有一个非守护线程时,则JVM的进程会退出。也就是说守护线程具有自动结束生命周期的特性。
守护线程经常作为一些后台任务,当希望关闭某些线程的时候,或者退出JVM进程的时候,一些线程能够自动关闭,此时就可以考虑守护ianc来完成这样的工作。
thread.setDaemon(true);//将此线程设置为守护线程。
三.线程interrupt
Object的wait方法;
Thread的join方法;
Thread的join方法;
InterruptibleChannel的io操作;
Selector的wakeup方法;
以上方法的调用会使得当前线程进入阻塞状态,而调用当前线程的interrupt方法,就可以打断阻塞。打断一个线程并不等于改线程的生命周期结束,仅仅是打断了当前线程的阻塞状态。
一旦线程在阻塞的情况下被打断,都会抛出一个成为InterruptedException的异常。
一个线程内部存在着名为interrupt flag的标识,如果一个线程被interrupt,那么它的flag将被设置,但如果当前线程正在执行可中断方法被阻塞是,调用interrupt方法将其中断,反而会导致flag被清除。
isInterrupted是Thread的一个成员方法,主要判断当前线程是否被中断,该方法仅仅是对interrupt标识的一个判断,并不会影响标识发生任何变化。
public void testInterrupt() throws InterruptedException {
Thread thread = new Thread(){
@Override
public void run() {
while(true) {
System.out.println("正在执行!");
}
}
};
thread.setDaemon(true);
thread.start();
TimeUnit.MILLISECONDS.sleep(2);
System.out.printf("Thread is interrupted? %s\n",thread.isInterrupted());
thread.interrupt();
System.out.printf("Thread is interrupted? %s\n",thread.isInterrupted());
}
Thread is interrupted? false
Thread is interrupted? true
public void testInterrupt() throws InterruptedException {
Thread thread = new Thread(){
@Override
public void run() {
while(true) {
System.out.println("正在执行!");
try {
TimeUnit.MINUTES.sleep(1);
} catch (InterruptedException e) {
System.out.printf("线程是否被中断? %s\n",isInterrupted());
e.printStackTrace();
}
}
}
};
thread.setDaemon(true);
thread.start();
TimeUnit.MILLISECONDS.sleep(2);
System.out.printf("Thread is interrupted? %s\n",thread.isInterrupted());
thread.interrupt();
System.out.printf("Thread is interrupted? %s\n",thread.isInterrupted());
}
Thread is interrupted? false
线程是否被中断? false
Thread is interrupted? false
interrupted是一个静态方法,判断当前线程是否被中断,调用该方法会直接擦除线程的interrupt标识,如果线程被打断,第一次调用interrupted方法会返回true,并且立即擦除interrupt标识;以后的调用都会返回false,除非在此期间线程又一次被打断。
四.正常关闭一个线程
1.捕获中断信号关闭线程
public void testInterrupt() throws InterruptedException {
Thread thread = new Thread(){
@Override
public void run() {
while(!isInterrupted()) {
System.out.println("正在执行!");
}
}
};
thread.setDaemon(true);
thread.start();
TimeUnit.MILLISECONDS.sleep(2);
System.out.printf("Thread is interrupted? %s\n",thread.isInterrupted());
thread.interrupt();
System.out.printf("Thread is interrupted? %s\n",thread.isInterrupted());
2.使用volatile开关控制
由于线程的interrupt标识很有可能被擦除,或者不会调用任何可中断方法,所以使用volatile修饰的开关flag关闭线程更常用。
private volatile boolean run = true;
@Test
public void testInterrupt() throws InterruptedException {
Thread thread = new Thread(){
@Override
public void run() {
while(run) {
System.out.println("正在执行!");
}
}
};
thread.setDaemon(true);
thread.start();
TimeUnit.MILLISECONDS.sleep(2);
run = false;
}