作为一名Android工程师,相信大家都应该经常会用到线程,或者异步操作,但是操作线程是一件有风险的事,下面我会列出我遇到过的一些坑。
由于技术有限,可能会有不对的地方,欢迎大家批评、指出问题,我会继续更新并改正,也欢迎交流,共同进步。
线程的概述(Introduction)
线程是一个程序的多个执行路径,执行调度的单位,依托于进程存在。 线程不仅可以共享进程的内存,而且还拥有一个属于自己的内存空间,这段内存空间也叫做线程栈,是在建立线程时由系统分配的,主要用来保存线程内部所使用的数据,如线程执行函数中所定义的变量。
注意:Java中的多线程是一种抢占机制而不是分时机制。抢占机制指的是有多个线程处于可运行状态,但是只允许一个线程在运行,他们通过竞争的方式抢占CPU。
基本状态:就绪、阻塞和运行
下面通过代码实际操作来讲解:
- 线程的创建:线程的创建有两种方式
①第一种(继承Thread):
public static class MineThread extends Thread {
@Override
public void run() {
while (!stop) {
System.out.println("Thread is running . . . ");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
②第二种(实现Runnalbe接口,重载Runnalbe接口中的run()方法):
public static class MineThread implements Runnable{
@Override
public void run() {
while (!stopB) {
System.out.println("Thread is running . . . ");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
这两种方法的区别我就不去说了,我曾看到过一篇很好的博客,介绍le这两种的区别,感兴趣的同学,可以去看看:
http://www.cnblogs.com/whgw/archive/2011/10/03/2198506.html
线程的停止:
终止线程的方法有三种:使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。
使用stop方法强行终止线程(这个方法不推荐使用,因为stop和suspend、resume一样,也可能发生不可预料的结果)。
使用interrupt方法中断线程。
在这三张方法中,第二种不可用,第三种有时候会出现无法终止线程的情况,实际上interrupt是终止阻塞的意思,所以,实际上我们如果想停止一个线程的最好的方法是使用退出标志位,然后再调用interrupt方法,一定要注意先后顺序。
下面我们分别通过代码测试这三种方法:
① 使用退出标志:
public class ThreadDemo {
public static boolean stop = false;
public static void main(String[] args) {
MineThread thread = new MineThread();
thread.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Stop thread . . . ");
stop = true;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("hread.isAlive()=" + thread.isAlive());
}
public static class MineThread extends Thread {
@Override
public void run() {
while (!stop) {
System.out.println("Thread is running . . . ");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
运行结果:
从运行结果看,线程被终止,说明此方法可行。
② 使用interrupt方法中断线程:
public class ThreadDemo {
public static boolean stop = false;
public static void main(String[] args) {
MineThread thread = new MineThread();
thread.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Stop thread . . . ");
try {
thread.interrupt();
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("hread.isAlive()=" + thread.isAlive());
}
public static class MineThread extends Thread {
@Override
public void run() {
while (!stop) {
System.out.println("Thread is running . . . ");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println(e.toString());
}
}
}
}
}
运行结果:
从上图运行结果看,interrupt只是中断了线程阻塞,而并没有终止线程。再看下面的代码:
public class ThreadDemo {
public static boolean stop = false;
public static void main(String[] args) {
MineThread thread = new MineThread();
thread.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Stop thread . . . ");
try {
thread.interrupt();
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("hread.isAlive()=" + thread.isAlive());
}
public static class MineThread extends Thread {
@Override
public void run() {
long startTime = System.currentTimeMillis();
while (!stop) {
while (System.currentTimeMillis() - startTime > 1000) {
startTime = System.currentTimeMillis();
System.out.println("Thread is running . . . ");
}
}
}
}
}
这段代码和上一段代码的区别在于没有调用Thread.sleep()方法阻塞线程,此时你会发现interrupt方法实际上没有起到任何实质性的作用。运行结果如下:
③退出标志+interrupt :
public class ThreadDemo {
public static boolean stop = false;
public static void main(String[] args) {
MineThread thread = new MineThread();
thread.start();
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Stop thread . . . ");
stop = true;
thread.interrupt();
try {
thread.interrupt();
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("hread.isAlive()=" + thread.isAlive());
}
public static class MineThread extends Thread {
@Override
public void run() {
while (!stop) {
System.out.println("Thread is running . . . ");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println(e.toString());
}
}
}
}
}
运行结果:
总结:从上面的运行结果来看,终止一个线程的最好方法是退出标志+interrupt,但是一定要注意先后顺序:退出标志–>interrupt