HT笔试随笔

选择

关于ArrayBlockingQueue说法不正确的是?

  • 其主要应用场景是“生产者-消费者”模型
  • 其是线程安全的
  • 允许元素为null
  • 必须显示的设置容量

并没有无参构造,所以必须要初始化长度,不让他变成一个无边界的数据队列,可能会存在内存过大的问题
内部实现了ReentrantLock锁,所以线程是安全的,

下面哪个流属于面向字符流

  • ObjectInputStream
  • BufferedWriter
  • FileInputStream
  • InputStreamReader

CharArrayReader 从字符数组读取的输入流
BufferedReader 缓冲输入字符流
PipedReader 输入管道
InputStreamReader 将字节转换到字符的输入流
FilterReader 过滤输入流
StringReader 从字符串读取的输入流
LineNumberReader 为输入数据附加行号
PushbackReader 返回一个字符并把此字节放回输入流
FileReader 从文件读取的输入流

以下关于线程通讯的说法错误的是

  • wait()有多个重载的方法,可指定等待时间
  • 可以调用wait()、notify()、notifyAll()三个方法实现线程通讯
  • wait()必须在sychronized方法或者代码块中使用
  • wait()、notify()、notifyAll()是Object类提供的方法、子类可以重写

wait()、notify()、notifyAll()都被final修饰子类不能重写

在java。util.concurrent.locks.AbstractQueueSychronizer的实现当中,使用了哪种数据结构?

  • 数组
  • 哈希表
  • 双向链表
  • 集合

查看源码易知是是双向链表

一下代码的运行结果

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


        Thread t = new Thread(){
            @Override
            public void run(){
                pong();
            }
        };

        t.run();
        System.out.println("ping");
    }

    static void pong(){
        System.out.println("pong");
    }
}

结果就是:
pong
ping

存在一个变量List strList,循环遍历List正确的项

System.out.println("方式一:");
        Iterator<String> it = strList.iterator();
        while(it.hasNext()){
            String str = it.next();
            System.out.print(str+" ");
        }
        System.out.println();

        System.out.println("方式二:");
        for(String str:strList){
            System.out.print(str+" ");
        }
        System.out.println();

        System.out.println("方式三");      //错误!!!!!!!
//        for(int i=0;i<strList.length;i++){
//            String str = strList[i];
//        }
        System.out.println();
        
        System.out.println("方式四:");     //错误!!!!!
//        List.foreach(strList,function(str){
//            
//        });

简答

已知二叉树的前序遍历和中序遍历,求后续遍历?

public class Solution {
    public static TreeNode reConstructBinaryTree(int[] prev, int[] in) {
        //不管什么遍历方式,结果长度肯定是一样的,都是总结点数
        if (prev.length != in.length || prev.length < 1) {
            return null;
        }

        //只有一个节点,那就是根节点
        if (prev.length == 1) {
            return new TreeNode(prev[0]);
        }

        //在中序遍历结果中找根节点
        int index = -1;
        for (int i = 0; i < in.length; i++) {
            if (in[i] == prev[0]) {
                index = i;
                break;
            }
        }
        //没找到,说明数据有问题
        if (index == -1) {
            return null;
        }

        //找到根节点了
        TreeNode root = new TreeNode(prev[0]);
        //得到左子树的前序遍历结果
        int[] lChildPrev = new int[index];
        System.arraycopy(prev, 1, lChildPrev, 0, index);
        //得到左子树的中序遍历结果
        int[] lChildin = new int[index];
        System.arraycopy(in, 0, lChildin, 0, index);
        //通过递归,得到左子树结构
        root.left = reConstructBinaryTree(lChildPrev, lChildin);

        //得到右子树的前序遍历结果
        int[] rChildPrev = new int[in.length - 1 - index];
        System.arraycopy(prev, index + 1, rChildPrev, 0, in.length - 1 - index);
        //得到右子树的中序遍历结果
        int[] rChildin = new int[in.length - 1 - index];
        System.arraycopy(in, index + 1, rChildin, 0, in.length - 1 - index);
        //通过递归,得到右子树结构
        root.right = reConstructBinaryTree(rChildPrev, rChildin);
        //得到完整的二叉树结构
        return root;
    }

    //测试
    public static void main(String[] args) {
        int[] prev = {1, 2, 4, 7, 3, 5, 6, 8};
        int[] in = {4, 7, 2, 1, 5, 3, 8, 6};
        TreeNode root = reConstructBinaryTree(prev, in);
        prevPrintTreeNode(root);
        System.out.println();
        inPrintTreeNode(root);
    }

    //测试结果
//1 2 4 7 3 5 6 8
//4 7 2 1 5 3 8 6
    public static void inPrintTreeNode(TreeNode root) {
        if (root == null) {
            return;
        }
        //运用了递归
        inPrintTreeNode(root.left);
        System.out.print(root.val + " ");
        inPrintTreeNode(root.right);
    }

    public static void prevPrintTreeNode(TreeNode root) {
        if (root == null) {
            return;
        }
        System.out.print(root.val + " ");
        //运用了递归
        prevPrintTreeNode(root.left);
        prevPrintTreeNode(root.right);
    }

    public static void postPrintTreeNode(TreeNode root) {
        if (root == null) {
            return;
        }
        //运用了递归
        postPrintTreeNode(root.left);
        postPrintTreeNode(root.right);
        System.out.print(root.val + " ");
    }
}


class TreeNode {
    int val;
    TreeNode left;
    TreeNode right;

    TreeNode(int x) {
        val = x;
    }
}

Sychronized和Lock的区别

在这里插入图片描述

参考:https://blog.csdn.net/hefenglian/article/details/82383569

一道SQL题,找出所有重复的字段,重复的字段仅输出一次

SELECT  distinct(email) FROM person 

在java.util.ThreadPoolExecutor的构造函数参数中,有corePoolSize、maximumSize、workQueue三个参数,那么当不断往线程池中添加任务时,这三个参数是如何影响线程池中的线程数的?

corePoolSize:

线程池的基本大小,线程池默认初始化线程数;只有在工作队列满了的情况下才在该基础上创建新的线程。

注意:在刚刚创建ThreadPoolExecutor的时候,线程并不会立即启动,而是要等到有任务提交时才会启动,除非调用了prestartCoreThread/prestartAllCoreThreads事先启动核心线程。再考虑到keepAliveTime和allowCoreThreadTimeOut超时参数的影响,所以没有任务需要执行的时候,线程池的大小不一定是corePoolSize。

maximumPoolSize:
线程池中允许的最大线程数,线程池中的当前线程数目不会超过该值。如果队列中任务已满,并且当前线程个数小于maximumPoolSize,那么会创建新的线程来执行任务。

这里要注意的是largestPoolSize,该变量记录了线程池在整个生命周期中曾经出现的最大线程个数。为什么说是曾经呢?因为线程池创建之后,可以调用setMaximumPoolSize()改变运行的最大线程的数目。

poolSize:

线程池中当前线程的数量,当该值为0的时候,意味着没有任何线程,线程池会终止;同一时刻,poolSize不会超过maximumPoolSize。

workQueue:
阻塞队列,队列里存放可执行的线程。

参考: https://blog.csdn.net/aitangyong/article/details/38822505

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值