java并行基础之注意事项

线程退出

  1. 尽量少用stop()方法(已过时方法),因为该方法会直接终止线程,释放持有的锁,从而无法保证事物的一致性。
    如下伪代码,就会造成User的id和name不是同一个值,因为可能没设置好setName操作就强制退出释放锁了:
public class TestStop {

    private static User u = new User();

    public static class Cc extends Thread{

        @Override
        public void run() {
           synchronized (u){
               Long v= System.currentTimeMillis();
               u.setId(v);
               //执行其他业务
               u.setName(v.toString());
           }
        }
    }
    
    @Test
    public void t(){
        while (true){
            Thread t = new Cc();
            t.start();
            t.stop();
        }
    }
}
  1. 可以通过调用interrupt()方法中断线程,中断后当前线程的isInterrupted()会变为true,然后根据sInterrupted()的状态去做一些操作退出这个线程。需要注意的是如果线程调用了Thread.sleep(),会因中断而抛出异常,它会清除掉中断标记,所以有时需要在catch中重新调用interrupt().

wait(),sleep()与suspend()的比较

  1. wait()需要在synchronized语句中使用,通过notify()唤醒其中一条wait的线程,
  2. sleep会让线程陷入等待状态,但是不会像wait那样释放锁
  3. suspend()(已过时方法,因为如果操作不当可能导致线程永远挂起,不释放锁)即挂起线程,这个时候线程会陷入等待状态,但是不会释放锁,需要通过resume()才能继续执行

join

  1. join()表示无限等待,它会一直阻塞当前线程,直到目标线程执行完毕
  2. join(long mills),如目标线程执行时间超过了mills,当前线程会因为“等不及”继续执行下去
  3. join的核心实现代码为:
//如果没有结束就wait
while (isAlive()){
   wait(0)
}

yield

执行yield (),会让出cpu资源,相当于把它当做一个优先级很低的线程来执行

守护线程Daemon

像垃圾回收那样的线程,在后台执行。如果除了守护线程没有其他线程在执行,守护线程会自动退出。把一个线程变成守护线程的操作为:

 Thread t = new Cc();
 t.setDaemon(true);

错误的加锁

不要做类似

 private static Integer i = 0;

    public static class Cc extends Thread{
        @Override
        public void run() {
           synchronized (i){
               i++;
           }
        }

因为Integer是不可变对象,i++;实际为

i = Integer.valueOf(i.intValue()+1);

这样会导致线程加锁的对象不一致,导致临界区代码控制出现问题

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值