线程停止
停止线程是在多线程开发时很重要的技术点,掌握线程停止技术可以对线程的停止进行有效的处理。
停止线程的方法
在Java 中有3种方法可以终止正在运行的线程:
- 使用退出标志,使线程正常退出,使run方法执行完后线程终止。
- 使用stop方法强制终止相册,但是不推荐使用这个方法,因为stop和suspend及resume一样,都是废弃过期的方法,不推荐使用,如果使用可能产生不可预料的结果。
- 使用interrupt方法中断线程。
interrupt 停止线程
调用interrupt() 方法仅仅是在当前线程中打了一个停止的标记,并不是真的停只线程。
如下示例:
public class MyThead extends Thread {
@Override
public void run() {
for (int i = 0; i < 100; i ++) {
System.out.println("Thread num i:" + i);
}
}
}
public class ThreadMain {
public static void main(String[] args) {
MyThead thead = new MyThead();
thead.start();
thead.interrupt();
}
}
最后在介绍连个方法:
- this.interrupted();
说明:测试氮气线程是否已经是中断状态,执行后具有将状态标志置清除为false的功能。 - this.isInterrupted();
说明:测试线程Thread对象是否已经是中断状态,但是不清除状态标志。
通过调用interrupt() 方法进行“停止”线程
示例代码如下:
public class MyThead extends Thread {
@Override
public void run() {
for (int i = 0; i < 1000000; i ++) {
if (this.interrupted()) {
System.out.println("跳出了for循环.......");
break;
}
System.out.println("Thread num i:" + i);
}
}
}
public class ThreadMain {
public static void main(String[] args) {
try {
MyThead thead = new MyThead();
thead.start();
Thread.sleep(10);
thead.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
通过上面的方法可以结束for循环,但是如果for循环后面还有代码,就要继续执行后面的代码,也就是说没有停止线程。使用要根据具体情况进行选择使用,
使用异常停止线程
这种方法是在线程运行时,在要停止线程时抛出一个异常,使线程被迫停止。
示例代码:
public class MyThead extends Thread {
@Override
public void run() {
try {
for (int i = 0; i < 1000000; i ++) {
if (this.interrupted()) {
System.out.println("跳出了for循环.......");
throw new InterruptedException("");
}
System.out.println("Thread num i:" + i);
}
System.out.println("我还没有结束,我还在运行哦........");
}catch (InterruptedException e) {
System.out.println("线程结束了");
}
}
}
public class ThreadMain {
public static void main(String[] args) {
try {
MyThead thead = new MyThead();
thead.start();
Thread.sleep(10);
thead.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
说明:
- 将所有需要在线程中运行的的代码放在
try catch
中,当想要结束线程运行的时候抛出个异常就可以了。
2.如果线程正在运行,并且在sleep状态下,通过异常方法停止线程会清除停止状态值,使之成为false(指的是interrupt 的值); - 只要sleep调用interrupt() 方法就会有异常抛出。
使用return 和 interrupt 结合停止线程
示例代码:
public class MyThead extends Thread {
@Override
public void run() {
for (int i = 0; i < 1000000; i ++) {
if (this.interrupted()) {
System.out.println("线程要结束啦......");
return;
}
System.out.println("Thread num i:" + i);
}
System.out.println("我还没有结束,我还在运行哦........");
}
}
public class ThreadMain {
public static void main(String[] args) {
try {
MyThead thead = new MyThead();
thead.start();
Thread.sleep(10);
thead.interrupt();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
线程暂停
线程暂停意味着此线程还可以继续运行。
suspend 和resume 方法
示例代码:
public class MyThead extends Thread {
@Override
public void run() {
try {
for (int i = 0; i < 1000; i ++) {
Thread.sleep(1000);
System.out.println("Thread num i:" + i);
}
System.out.println("线程结束了........");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public class ThreadMain {
public static void main(String[] args) {
try {
MyThead thead = new MyThead();
thead.start();
Thread.sleep(2000);
thead.suspend();
Thread.sleep(5000);
thead.resume();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
上面是线程暂停的方法,但是,但是,注意,注意,这两个方法已经被弃用了。
下面说一下使用这两个方法的缺点:
- 线程独占
如果使用不当,极容易造成公共的同步对象独占,使得其他线程无法访问公共同步对象。
下面写一个简单例子理解一下:
public class MyObject {
private int sign;
public void setSign(int sign) {
this.sign = sign;
}
public synchronized void putString() {
if (sign == 1) {
System.out.println("开始 suspend ");
Thread.currentThread().suspend();
System.out.println("结束suspend ");
}
}
}
public class ThreadMain {
public static void main(String[] args) {
try {
MyObject object = new MyObject();
object.setSign(1);
Thread thread1 = new Thread(new Runnable() {
@Override
public void run() {
object.putString();
}
});
thread1.start();
Thread.sleep(3000);
object.setSign(2);
Thread thread2 = new Thread(new Runnable() {
@Override
public void run() {
object.putString();
}
});
thread2.start();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
上面被线程1独占了,所以后面的线程都阻塞住了。
- 数据不同步:这里就不举例子了,挺好理解的。
介绍一个方法
yield() 方法:
yield() 方法的作用是放弃当前的CPU资源,将它让给其他的任务去占用CPU执行时间,但放弃的时间不确定,有可能刚刚放弃,马上又获得CPU时间片。
网友评论