多线程的一些心得

在此总结下自己在面试过程中面试官问的问题,以便于以后查阅:

1.谈谈你对java中hashMap的认识。

     hashMap是java中自带的一个类,其作用为存储key-value形式的数据,key、value都可为泛型。其key值允许有一个有null,其value值可为null。hashMap的初始size为16,负载因子为0.75,如果数据的个数超过16 * 0.75时就会自动进行扩容操作。

    hashMap的查找时间复杂度理想情况是O(1),但在日常业务中可能会出现哈希碰撞。hash碰撞的意思是两个不同的key在经过hash()之后得到了一样的hashCode,这时候hashMap的处理方式是将其放在该hashCode对应的bocket中,而这两个元素就已链表的形式凭借在一起,这更进一步的印证了hashMap数组 + 双向列表的结构。

     在取值的时候也是一样,先根据hashCode定位到指定的bocket,如果有hash冲突再用equals()方法来比较key从而取到目标的key-value。

     1.7和1.8的区别是1.8在1.7的基础上将链表结构在满足一定条件下修改为红黑树的结构,一旦这条件不满足红又会自动调整为链表结构。

 2.你对多线程了解吗?谈谈线程的几个状态。

   首先我们点进入thread里面,里面有线程的state

* <ul>
* <li>{@link #NEW}<br>
*     A thread that has not yet started is in this state.
*     </li>
* <li>{@link #RUNNABLE}<br>
*     A thread executing in the Java virtual machine is in this state.
*     </li>
* <li>{@link #BLOCKED}<br>
*     A thread that is blocked waiting for a monitor lock
*     is in this state.
*     </li>
* <li>{@link #WAITING}<br>
*     A thread that is waiting indefinitely for another thread to
*     perform a particular action is in this state.
*     </li>
* <li>{@link #TIMED_WAITING}<br>
*     A thread that is waiting for another thread to perform an action
*     for up to a specified waiting time is in this state.
*     </li>
* <li>{@link #TERMINATED}<br>
*     A thread that has exited is in this state.
*     </li>
* </ul>

         NEW新建状态,刚刚创建线程,此时线程并没有运行

         RUNNABLE:运行状态,此时的线程在Java虚拟机里面运行。

         BLOCKED:阻塞状态,此时线程进入等待状态,放弃了CPU的使用权。

         WAITING:等待状态,线程处于等待状态。

         TIMED_WAITING:等待超时状态,超时以后自动返回。

         TERMINATED:线程终止状态。     

这里有一个需要注意的地方,如果是继承Thread的话,启动了thread.start(),此时线程并没用处于运行状态,当cpu分给线程资源的时候才算是真正的出入执行状态。

3.我想顺序输出A.B.C三个线程,该如何处理呢?

      (1).如果是使用继承Thread,那么直接使用其中自带的一个方法join();

如下:

public final synchronized void join(long millis)
throws InterruptedException {
    long base = System.currentTimeMillis();
    long now = 0;

    if (millis < 0) {
        throw new IllegalArgumentException("timeout value is negative");
    }

    if (millis == 0) {
        while (isAlive()) {
            wait(0);
        }
    } else {
        while (isAlive()) {
            long delay = millis - now;
            if (delay <= 0) {
                break;
            }
            wait(delay);
            now = System.currentTimeMillis() - base;
        }
    }
}

   thread.join()是被final and synchronized 修饰的,因此如果线程如果要保持相关顺序行的话直接使用join()方法便能保证!如果不设置millis,则后面的thread就会一直等待,知道前面的thread执行完成才能够执行。如果设置了millis的话,那么在执行时间等于这个值之后,就会开始执行下一个线程。

Demo:

public class Demo {
    public static void main(String[] args) {

        for(int i = 0;i < 100;i ++){
            Thread t3 = new NewThread("线程3");
            Thread t1 = new NewThread("线程1");
            Thread t2 = new NewThread("线程2");
            try{
                t1.start();
                t1.join();
                t2.start();
                t2.join();
                t3.start();
                t3.join();
            }catch (Exception e){
                System.out.println(e);
            }
        }
    }
}

 4.volatile关键字的作用是什么?

    volatile是一个类型修饰符,其修饰的对象在多线程操作下保证了对象的可见性。在编译器和处理器对class文件进行编译或者预处理的时候,为了提高效率往往会多指令进行重排序。使用了volatile关键字修饰之后就禁止对指令进行重排序,这便是volatile的另一个特性:有序性。如果是在单个线程的读/写下,能够保证其原子性,但是如果是i++这种形式下便无法保证其原子性。

原创文章 18 获赞 3 访问量 1640

猜你喜欢

转载自blog.csdn.net/qq_39941165/article/details/103868325
今日推荐