关于线程和多线程,JAVA高并发程序设计

时间:2021-05-18 23:50:06

主要整理一些关于线程的知识,尽量做到言简意赅,面试的时候用。

线程

前段时间找工作,很多次问到关于线程的问题,回答的时候就开启背书模式:线程是轻量级的进程,是程序执行的最小单位….现在想想,面试官要听的肯定不是这些,如果只知道这些,那还怎么守护达康书记的GDP。关于线程和多线程,JAVA高并发程序设计


面试官:来说下线程吧。
程序猿:线程用的是Thread这个类和Runnable这个接口…
面试官:那你来说下Thread和Runnable的区别。
程序员:一个继承Thread方法,重写run()方法。另一个实现Runnable接的run()方法,两者都是通过start()方法实现多线程。

扩展:start()表示创建一个新的线程,而run()只是在当前线程里调用run()方法,Runnable和Thread比较:

  • JAVA是单继承,Thread有局限性;
  • Runnable数据共享;

面试官:说下线程的几个方法。
程序员:主要用的是这么几个:

  • stop():停止线程,不过线程已经废弃了,因为这个方法太暴力了,说停就停。比如,A写一个数据data,B等待去读写到一半的时候,调用了stop,数据损坏,B此时去读的话,就是错误的数据了,解决方法就是,自定义停止线程的条件。
  • wait()和notify():当一个对象调用了waut后,当前线程会一直等待,直到其他线程调用了notify。notify和notifyAll的区别:nofity在等待结束后,会随机抽取一个线程,nofityAll是所有线程。wait和sleep的区别:wait可以重新唤醒,会释放目标对象的锁。大概是下图那个意思,重点是流程,现实中开明的父母还是很多的哈关于线程和多线程,JAVA高并发程序设计
  • suspend()和resume():不推荐用,不会释放锁。
  • join()和yield():join是等待线程完成后再去执行.。比如:
    class OneThread extends Thread{
    @Override
    public void run() {
    for(int i =0;i<1000000;i++);
    }
    }

    直接调用OneThread.start(),输出i结果会很小,调用OneThread.join,会等待线程执行完成,输出i=1000000。

面试官:说一下volatile吧。
程序猿:volatile修饰表示不能随意改变目标指令。
这跟JAVA的内存模型有关系,JVM的三个特征:

  • 原子性:不能中断,比如int a,两个线程无论用任何方式赋值,最后a的结果只能是两个中的一个。PS:long类型比较特殊,因为他有64位,在32为系统上有出入。
  • 可见性:窜行程序,可见性问题不存在,修改值后,后续的操作都是修改后的值。并行程序会出现问题:A修改了一个全局变量,其他线程不一定知道。
  • 有序性:指令重排,后面的代码肯呢个会先执行,无法判断会不会出现这个问题,同样在窜行中不会出现。
    在实际的运用中,我们常用的单例模式,比较好的写法其实是这样:
public class Simple{


private static volatile Simple simple;

public static Simple getInstance(){
if (null == simple) {
synchronized (Simple.class) {
if (null == simple) {
simple = new Simple();
}
}
}
return simple;
}

}

这样写效率低了些,但保证了安全性。


面试官:说下synchronized的作用
程序员:实现线程间的同步,对需要同步的代码加锁,比如A在写入时,B不能读也不能写,保证线程间的安全性。主要的几种用法:

  • 指定对象加锁;
  • 作用于实例方法;
  • 作用于静态方法;

最后会问一些其他跟线程有关的问题,比如HashMap,ArrayList是线程安全吗?为什么?这些网上都有很多,可以去找下这方面的资料

有哪里说错的或是不好的,欢迎留言。最后感叹下,现在的公司对技术要求越来越高了关于线程和多线程,JAVA高并发程序设计