线程间交互及相关1

如何结束一个线程?

1、使用 Thread.stop() ,可以直接结束线程,如下代码,当 thread 线程执行一百万次打印,主线程睡 5 秒之后对 thread 进行 stop。通过打印日志可以发现线程确实立即被中断了,但是在代码中能发现 thread.stop() 是被废弃的 Api,这是因为 thread.stop() 导致的结果是不可预期的,它会立即中断线程,中间的过程无法控制,不能控制中间的过程,就像突然断电。

2、使用thread.interrupt(): 给线程一个停止的标记,需要自己在线程中判断 Thread.interrupted() 或者 isInterrupted() 手动进行收尾处理,否则不起作用。这是一个温和版本的中指,建议使用。

@OnLifecycleEvent(Lifecycle.Event.ON_CREATE)
public void onCreate() {
Log.d(TAG, "onCreate");
Thread thread = new Thread() {
@Override
public void run() {
super.run();
for (int i = 0; i < 1_000_000; i++) {
if (Thread.interrupted()) {
//收尾处理
return;
}
Log.d(TAG, i + "");
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
//收尾处理
return;
}
}
}
};
thread.start();
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//thread.stop();
thread.interrupt();
}

thread.stop():可以立即终止线程,但是不可控。不建议使用;

thread.interrupt():给线程一个中断标记,自己在目标线程中配合进行操作了;

Thread.interrupted()isInterrupted():前者判断完后会重置 interrupt为 false,后者不会,通常使用前者。

为什么Thread.sleep()一定要抛出InterruptedException e异常呢:因为假设子线程正在sleep ,而主线程此时对其发送了interrupt,由于休眠并不是消耗资源的操作,所以不会等线程走完就会立刻走到 catch中抛出InterruptedException异常,提示外部对其进行了interrupt,若需要终结可以在catch中进行处理,同时,当抛出InterruptedException时就已经消化了interrupt事件,所以若不处理则在此之后Thread.interrupted()进行判断也是false,就好像什么都没发生过一样;

SystemClock.sleep() 就等于 Thread.sleep()不处理 catch 事件,简化了抛出异常不处理的代码。

Thread.wait()

Thread.wait():会使线程进入等待队列。

public class WaitDemo {

private String shardString;

private synchronized void initString() {
shardString = "分享";
notifyAll();
}

private synchronized void printString() {
while (shardString == null){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
//notifyAll之后从这里开始继续执行
}
System.out.println("String" + shardString);
}

public void run() {
Thread thread1 = new Thread() {
@Override
public void run() {
super.run();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
printString();
}
};
thread1.start();

Thread thread2 = new Thread() {
@Override
public void run() {
super.run();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
initString();
}
};
thread2.start();
}
}

如上所示代码,由于睡眠时间不同(这里的睡眠只是模拟现实操作),导致 thread1 的执行总是在线程2 之前,但此时线程 thread2中还未对shardString值进行初始化,

所以这里可以对thread2进行wait操作,暂时将优先级让出来。然后在thread2shardString进行了初始化值,可以调用 notifyAll() 吧所有的等待队列进行刷新。

刷新之后,thread2会从wait 后面继续开始执行代码。

注意:wait 是一个 object 方法,并不是一个线程方法,因为 wait 和是要伴随着唤醒的,都是monitor 调用的,因此是一个 object 方法。

0%