Java面试题系列——JavaSE面试题(线程三)

1、同步函数和静态同步函数之间有什么区别?

(1)同步函数的锁是固定的的this

public synchronized void show()
{
    if(num > 0)
    {
        try{Thread.sleep(10);} catch(InterruptedException e){};
        System.out.println(Thread.currentThread().getName() + "......function......" + num--);
    }
}

 (2)静态同步函数使用的锁是该函数所属字节码文件对象,可以使用this.getClass()方法获取,也可以用当前 类名.class表示。静态方法中没有this对象,静态方法没有所属对象。而任何类在加载的时候都会有字节码类对象,用getClass获取。

public static synchronized void show()//静态方法中没有this对象,静态方法没有所属对象//任何类在加载的时候都会有字节码类对象,用getClass获取。
{
    if(num > 0)
    {
        try{Thread.sleep(10);} catch(InterruptedException e){};
        System.out.println(Thread.currentThread().getName() + "......function......" + num--);
    }
}

2、什么是多线程死锁?

        死锁就是两个或者多个线程,相互占用对方需要的资源,而都不进行释放,导致彼此之间都相互等待对方释放资源,产生了无限制等待的现象。死锁一旦发生,如果没有外力介入,这种等待将永远存在,从而对程序产生严重影响。

3、wait() 和notify() 方法的区别?

(1)notify()随机唤醒等待队列中的一个线程,wait()当条件不成熟时就等待。

4、同步与异步的区别

        同步:同步是指一个进程在执行某个请求的时候,如果该请求需要一段时间才能返回信息,那么这个进程会一直等待下去,直到收到返回信息才继续执行下去。 

        异步:异步是指进程不需要一直等待下去,而是继续执行下面的操作,不管其他进程的状态,当有信息返回的时候会通知进程进行处理,这样就可以提高执行的效率了,即异步是我们发出的一个请求,该请求会在后台自动发出并获取数据,然后对数据进行处理,在此过程中,我们可以继续做其他操作,不管它怎么发出请求,不关心它怎么处理数据。

 5、线程的生命周期

         新建(new Thread):当创建Thread类的一个实例(对象)时,此线程进入新建状态(未被启动)。就绪(runnable):线程已经被启动,正在等待被分配给CPU时间片,也就是说此时线程正在就绪队列中排队等候得到CPU资源。运行(running):线程获得CPU资源正在执行任务(run()方法),此时除非此线程自动放弃CPU资源或者有优先级更高的线程进入,线程将一直运行到结束。死亡(dead):当线程执行完毕或被其它线程杀死,线程就进入死亡状态,这时线程不可能再进入就绪状态等待执行。堵塞(blocked):由于某种原因导致正在运行的线程让出CPU并暂停自己的执行,即进入堵塞状态。

 6、线程同步的几个方法

(1)同步方法:即有synchronized关键字修饰的方法。 由于java的每个对象都有一个内置锁,当用此关键字修饰方法时,内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。

package threadTest; 
 
public class Bank { 
 
  private int count =0;//账户余额 
 
  //存钱 
  public synchronized void addMoney(int money){ 
    count +=money; 
    System.out.println(System.currentTimeMillis()+"存进:"+money); 
  } 
 
  //取钱 
  public synchronized void subMoney(int money){ 
    if(count-money < 0){ 
      System.out.println("余额不足"); 
      return; 
    } 
    count -=money; 
    System.out.println(+System.currentTimeMillis()+"取出:"+money); 
  } 
 
  //查询 
  public void lookMoney(){ 
    System.out.println("账户余额:"+count); 
  } 
}

(2)同步代码块:即有synchronized关键字修饰的语句块。被该关键字修饰的语句块会自动被加上内置锁,从而实现同步。

package threadTest; 
 
public class Bank { 
 
  private int count =0;//账户余额 
 
  //存钱 
  public  void addMoney(int money){ 
 
    synchronized (this) { 
      count +=money; 
    } 
    System.out.println(System.currentTimeMillis()+"存进:"+money); 
  } 
 
  //取钱 
  public  void subMoney(int money){ 
 
    synchronized (this) { 
      if(count-money < 0){ 
        System.out.println("余额不足"); 
        return; 
      } 
      count -=money; 
    } 
    System.out.println(+System.currentTimeMillis()+"取出:"+money); 
  } 
 
  //查询 
  public void lookMoney(){ 
    System.out.println("账户余额:"+count); 
  } 
}

(3)使用特殊域变量(Volatile)实现线程同步:volatile关键字为域变量的访问提供了一种免锁机制,使用volatile修饰域相当于告诉虚拟机该域可能会被其他线程更新,因此每次使用该域就要重新计算,而不是使用寄存器中的值,volatile不会提供任何原子操作,它也不能用来修饰final类型的变量。

package threadTest; 
 
public class Bank { 
 
  private volatile int count = 0;// 账户余额 
 
  // 存钱 
  public void addMoney(int money) { 
 
    count += money; 
    System.out.println(System.currentTimeMillis() + "存进:" + money); 
  } 
 
  // 取钱 
  public void subMoney(int money) { 
 
    if (count - money < 0) { 
      System.out.println("余额不足"); 
      return; 
    } 
    count -= money; 
    System.out.println(+System.currentTimeMillis() + "取出:" + money); 
  } 
 
  // 查询 
  public void lookMoney() { 
    System.out.println("账户余额:" + count); 
  } 
}

(4)使用重入锁实现线程同步:在JavaSE5.0中新增了一个java.util.concurrent包来支持同步。ReentrantLock类是可重入、互斥、实现了Lock接口的锁, 它与使用synchronized方法和快具有相同的基本行为和语义,并且扩展了其能力。ReenreantLock类的常用方法有:ReentrantLock() : 创建一个ReentrantLock实例,lock() : 获得锁,unlock() : 释放锁。

package threadTest; 
 
import java.util.concurrent.locks.Lock; 
import java.util.concurrent.locks.ReentrantLock; 

public class Bank { 
 
  private int count = 0;// 账户余额 
 
  //需要声明这个锁 
  private Lock lock = new ReentrantLock(); 
 
  // 存钱 
  public void addMoney(int money) { 
    lock.lock();//上锁 
    try{ 
    count += money; 
    System.out.println(System.currentTimeMillis() + "存进:" + money); 
 
    }finally{ 
      lock.unlock();//解锁 
    } 
  } 
 
  // 取钱 
  public void subMoney(int money) { 
    lock.lock(); 
    try{ 
 
    if (count - money < 0) { 
      System.out.println("余额不足"); 
      return; 
    } 
    count -= money; 
    System.out.println(+System.currentTimeMillis() + "取出:" + money); 
    }finally{ 
      lock.unlock(); 
    } 
  } 
 
  // 查询 
  public void lookMoney() { 
    System.out.println("账户余额:" + count); 
  } 
}

(5)使用局部变量实现线程同步:如果使用ThreadLocal管理变量,则每一个使用该变量的线程都获得该变量的副本,副本之间相互独立,这样每一个线程都可以随意修改自己的变量副本,而不会对其他线程产生影响。ThreadLocal与同步机制都是为了解决多线程中相同变量的访问冲突问题,前者采用以”空间换时间”的方法,后者采用以”时间换空间”的方式。

package threadTest; 
 

public class Bank { 
 
  private static ThreadLocal<Integer> count = new ThreadLocal<Integer>(){ 
 
    @Override
    protected Integer initialValue() { 
      // TODO Auto-generated method stub 
      return 0; 
    } 
 
  }; 
 
  // 存钱 
  public void addMoney(int money) { 
    count.set(count.get()+money); 
    System.out.println(System.currentTimeMillis() + "存进:" + money); 
 
  } 
 
  // 取钱 
  public void subMoney(int money) { 
    if (count.get() - money < 0) { 
      System.out.println("余额不足"); 
      return; 
    } 
    count.set(count.get()- money); 
    System.out.println(+System.currentTimeMillis() + "取出:" + money); 
  } 
 
  // 查询 
  public void lookMoney() { 
    System.out.println("账户余额:" + count.get()); 
  } 
}

持续更新中,敬请期待!

参考文章:

同步代码块、同步函数和静态同步函数_jamie_byr的博客-CSDN博客_静态同步函数

多线程理解(十三) 死锁_ljh要努力的博客-CSDN博客_多线程死锁是什么意思

 Thread线程中wait()与notify()有何区别_luo_boke的博客-CSDN博客_thread wait

wait, notify 和 notifyAll区别_Coder112233的博客-CSDN博客

线程生命周期_彷徨的石头的博客-CSDN博客_线程的生命周期

线程的生命周期_ycmnzmm的博客-CSDN博客_线程的生命周期

线程同步的几种方式 - 知乎

https://www.jb51.net/article/124073.htm

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小海海不怕困难

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值