关于线程开启的迷惑
为了秋招进行Java基础深入补习,看到Thread源码中有一个Run方法,如下:
@Override
public void run() {
if (target != null) {
target.run();//private Runnable target;
}
}
如果跟我一样小白的同学也许会有疑问,咦,怎么最后在线程中还是由传入的Runnable接口多态调用run()方法的呢?这里应该不是很难理解,我们传入了一个Runnable的子类(更多是使用匿名内部类),之后父对象引用子类对象,然后多态调用run方法
带着这个疑问,我做了以下测试:
public class TestJava {
public static void main(String[] args) {
//获取主线程中的线程名字
System.out.println("Thread"+Thread.currentThread().getName());
new Thread(new Runnable() {
@Override
public void run() {
//获取该方法执行的线程名字
System.out.println("Thread"+Thread.currentThread().getName());
}
}).start();
new Runnable(){
@Override
public void run() {
//获取该方法执行的线程名字
System.out.println("Runnable"+Thread.currentThread().getName());
}
}.run();
//这里根本就不是开启另外一条线程
MyRunnable mr = new MyRunnable();
mr.run();
}
}
class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println("MyRunnable"+Thread.currentThread().getName());
}
}
测试结果:
这里可以看出,除了使用new Thread(Runnable).start()中打印出的线程名字不同之外,其他都是在主线程中运行的,所以其他都没有开启子线程,都是在main线程执行的
理解中断
当线程的run方法执行完毕之后,或者在方法中还没有捕获异常的时候,线程将终止.早前Java中提供了stop方法,其他线程可以调用它来终止线程,但这个方法现在早已被弃用了.现在一般使用interrupt方法来请求中断线程
1.当一个线程调用interrupt方法时候,线程的中断标识位将被置位(中断标识位为true),线程会不时地检测这个中断标识位,以判断线程是否需要被中断.
2.要想知道线程是否被置位,可以调用Thread.currentThread().isInterrupted()
3.如果一个线程被阻塞,就无法检测中断状态.如果一个线程处于阻塞状态,线程会在检查中断标识位时发现中断标识位为true,则会在阻塞状态调用处抛出InterruptedException异常,并且在异常抛出前将线程的中断标识位复位,即重新设置为false.
4.需要注意的是被中断的线程不一定会终止,中断线程只会引起线程的注意,被中断的线程可以决定如何响应中断
测试代码:
public class Main {
public static int count = 0;
public static void main(String[] args) {
Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
System.out.println("我还没有被中断" + ++count);
//为了让其进行阻塞状态
Thread.sleep(500);
} catch (InterruptedException e) {
//抛出这异常之前会把Thread.currentThread().isInterrupted()置为false
count = 0;
System.out.println("被中断了");
}
}
}
});
t1.start();
try {
//这里主要让主线程睡眠,为了确保t1保证开启了
Thread.sleep(1000);//改为5000更好的
t1.interrupt();
} catch (InterruptedException e) {
}
}
}
结果:
可见:中断线程并不是终止线程的意思,要想使用中断线程来终止线程,就要在抛出异常的时候
try {
....
} catch (InterruptedException e) {
//其实这句话就是把中断状态interrupt=true;
Thread.currentThread().interrupt();
count = 0;
System.out.println("被中断了");
}
还有两篇很好的文章:
1.Java 多线程同步与死锁 - 百炼成钢 - 博客频道 - CSDN.NET
2.Java多线程系列目录(共43篇) - 如果天空不死 - 博客园