Thread.stop()
当我们使用Thread.stop()方法去停止线程时,这个方法会报错,抛出了
UnsupportedOperationException异常,
它在JDK中已经被声明“过期/作废”的方法,显然它在功能上有缺陷,不建议使用。
interrupt()方法
interrupt()方法的简单理解 interrupt() 方法只是改变中断状态而已,
它不会中断一个正在运行的线程。
这一方法实际完成的是,给受阻塞的线程发出一个中断信号,这样受阻线程就得以退出阻塞的状态。
更确切地说,如果线程被 Object.wait, Thread.join 和 Thread.sleep三种方法之一阻塞,
此时调用该线程的interrupt()方法, 那么该线程将抛出一个 InterruptedException中断异常(该线程必须事先预备好处理此异常), 从而提早地终结被阻塞的状态。
看到这里,可能有人会说 Object.wait, Thread.join 和 Thread.sleep 是什么东西?这里介绍下,仔细看下:
线程中常用的方法 sleep、wait、join
sleep:阻塞当前线程,并不释放锁对象 (当前线程让出cpu资源,不会影响锁,能够在程序的任何地方使用)
wait: 阻塞当前线程,释放锁对象 给其他竞争同一个锁的线程
调用wait方法会使该线程进入等待状态,并且会释放被同步对象的锁
wait、notify以及notifyAll都是Object对象的方法,他们必须在被 synchronized 同步的方法或代码块中调用,否则会报错。
notify操作可以唤醒一个因执行wait而处于阻塞状态的线程,使其进入就绪状态,被唤醒的线程会去尝试着获取对象锁,然后执行wait之后的代码。
如果发出notify操作时,没有线程处于阻塞状态,那么该命令会忽略。
注意执行notify并不会马上释放对象锁,会等到执行完该同步方法或同步代码块后才释放。
notifyAll方法可以唤醒等待队列中等待同一共享资源的“全部”线程从等待状态--->就绪状态,进行锁争夺,类似第3天后面逻辑。
public class WaitDmo {
private Student s = new Student();
class T1 extends Thread{
@Override
public void run() {
synchronized (s){
try {
System.out.println("Hello T2");
if (s.getName() == null){
s.wait();
}
System.out.println(s);
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
class T2 extends Thread{
@Override
public void run() {
synchronized (s){
try {
System.out.println("Hello T1");
s.setName("lily");
s.notify();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
@Test
public void test() throws InterruptedException {
Thread t1 = new T1();
Thread t2 = new T2();
t1.start();
t2.start();
}
}
当线程一阻塞后,线程二就执行了,
值得注意的是
线程一最后又打印了student对象(name=lily),
是因为线程二唤醒了线程一,
wait和notify搭配使用实现了线程的通信,
对于wait阻塞,也可以直译理解为等待更为贴切。
join: 等待当前线程到死 (可以实现 让多个线程排队执行)
public class MyTread implements Runnable {
private static volatile int num = 0;
private String name;
public MyTread(String name) {
this.name = name;
}
@Override
public void run() {
num++;
System.out.println(name+"num:"+num);
}
}
@Test
public void test() throws InterruptedException {
for (int i = 0; i < 10; i++) {
Thread t = new Thread(new MyTread("Thread-"+i));
t.start();
}
}
//这个执行打印的数据肯定不是顺序的
//可以看到线程并没有顺序执行
如果我们换成下面这样,就会有线程顺序执行了:
@Test
public void test() throws InterruptedException {
for (int i = 0; i <10; i++) {
Thread t = new Thread(new MyTread("Thread-"+i));
t.start();
//就是这里,等待当前线程到死
t.join();
}
}