终止线程的方法

1,014 阅读2分钟

线程安全要符合两点:原子性&可见性(加入个人理解:一致性,主内存和和线程内存的一致性) 结合这两点展开对volatile和synchronize的理解

  1. 使用退出标志,使线程正常退出,也就是当run方法完成后线程终止。 
    
  2. 使用stop方法强行终止线程(这个方法不推荐使用,因为stop和suspend、resume一样,也可能发生不可预料的结果)因为stop会释放锁,数据一致性得不到保障。
    
  3. 使用interrupt方法中断线程。
    

(1)线程处于阻塞状态,如使用了sleep方法。 (2)使用while(!isInterrupted()){…throw new InterruptedException…} (推荐方法:因为异常可以向上抛出,事件可以传播) (3)interrupt与return结合(不能像使用throw new InterruptedException那样传播事件)

suspend、resume为什么废弃?

  1. 使用不当,造成同步方法独占,其他线程无法访问,造成死锁。
  2. 容易出现线程的暂停导致数据不同步。 Thread.suspend 天生容易引起死锁。如果目标线程挂起时在保护系统关键资源的监视器上持有锁,那么其他线程在目标线程恢复之前都无法访问这个资源。如果要恢复目标线程的线程在调用 resume 之前试图锁定这个监视器,死锁就发生了。这种死锁一般自身表现为“冻结( frozen )”进程。

GC是一个守护线程

关于变量是否线程安全的问题: int num = 0在add方法外,如果多个run方法调用add方法时:非安全。 如果num = 0 在方法里面,则安全。

如果对这个num进行set get value,都要加synchronize,只对set加不对get加synchronize,那么另外的线程在get时会出现“脏读”。 可以参考《java并发编程》65页。

上面这一块儿也挺重要的,仔细阅读。

synchronize锁重入:自己可以再次获取自己的内部锁。

synchronize代码块带你的同步性问题,79也了解一下,第一遍不太懂。

package com.sankuai.qcs.risk.web.service;

/**

  • Description:
  • @author: zhangleilei
  • @date: 2018/2/5 */

public class Test { public static void main(String[] args) { Add[] adder = new Add[10]; for (int i = 0; i < 10; i++) { adder[i] = new Add(); adder[i].start(); } } }

class Add extends Thread { volatile public static int count = 0;

synchronized public void add() { for (int i = 0; i < 10; i++) { count++; } System.out.println("Thread:" + Thread.currentThread().getName() + ",Count:" + count); }

@Override
public void run() {
    super.run();
    add();
}

}

Thread:Thread-0,Count:10 Thread:Thread-1,Count:20 Thread:Thread-2,Count:30 Thread:Thread-3,Count:40 Thread:Thread-4,Count:50 Thread:Thread-5,Count:60 Thread:Thread-6,Count:70 Thread:Thread-7,Count:80 Thread:Thread-8,Count:90 Thread:Thread-9,Count:100