首页 > 其他分享 >多线程--面试题整理

多线程--面试题整理

时间:2022-12-07 10:34:25浏览次数:36  
标签:面试题 多线程 -- 对象 线程 内存 进程 command null

简述线程,程序、进程的基本概念

线程:与进程相似,但线程是比进程更小的执行单位。一个进程在其执行的过程中可以产生多个线程。与进程不同的是同类的多个线程共享同一块内存空间和一组系统资源,所以系统在产生一个线程,或是在各个线程之间作切换工作时,负担要比进程小得多,也正因为如此,线程也被称为轻量级进程。
程序:是含有指令和数据文件,被存储在磁盘或其他的数据存储设备中,也就是说程序是静态代码。
进程:是程序的一次执行过程,是系统运行程序的基本单位,因此进程是动态的。换句话说,当程序在执行时,将会被操作系统载入内存中。 线程是进程划分成的更小的运行单位。线程和进程最大的不同在于基本上各进程是独立的,而各线程则不一定,
因为同一进程中的线程极有可能会相互影响。

线程有哪些基本状态

Java 线程在运行的生命周期中可能处于下面 6 种不同状态
新建(NEW)可运行(RUNNABLE)阻塞(BLOCKED)等待(WAITING)超时等待(TIMED_WAITING)终止(TERMINATED)
可运行状态是个复合状态,又可以分为READY:就绪状态。RUNNING:表示该线程正在执行。

如何理解内存泄漏问题?有哪些情况会导致内存泄露?如何解决

内存泄漏:对于应用程序来讲,当对象不再被使用的时候,但是java的垃圾回收不能回收他们,就产生了内存泄漏。

上图中包含了未引用对象和引用对象。未引用对象将会被垃圾回收器回收,而引用对象却不会。未引用 对象很显然是无用的对象。然而,无用的对象并不都是未引用对象,有一些无用对象也有可能是引用对象,这部分对象正是内存泄露的来源。
比如说:对象A引用了对象B,A的生命周期比B的生命周期长,当对象B执行完,垃圾回收器是不会回收对象B的,这就可能造成内存不足的问题。因为A还引用着B,还可能引用其他比A生命周期短的对象。
怎样阻止内存泄露
1.使用List、Map等集合时,在使用完成后赋值为null
2.使用大对象时,在用完后赋值为null
3.目前已知的jdk1.6的substring()方法会导致内存泄露
4.避免一些死循环等重复创建或对集合添加元素,撑爆内存
5.简洁数据结构、少用静态集合等
6.及时的关闭打开的文件,socket句柄等
7.多关注事件监听(listeners)和回调(callbacks),比如注册了一个listener,当它不再被使用的时候,忘了注销该listener,可能就会产生内存泄露。

线程池的原理,为什么要创建线程池?创建线程池的方式;

线程池的优点:
1、线程是稀缺资源,使用线程池可以减少创建和销毁线程的次数,每个工作线程都可以重复使用。
2、可以根据系统的承受能力,调整线程池中工作线程的数量,防止因为消耗过多内存导致服务器崩溃。
线程池的实现原理:

线程池的创建:

/**
* corePoolSize:线程池核心线程数量 
* maximumPoolSize:线程池最大线程数量 
* keepAliverTime:当活跃线程数大于核心线程数时,空闲的多余线程最大存活时间 
* unit:存活时间的单位 
* workQueue:存放任务的队列 
* handler:超出线程范围和队列容量的任务的处理程序
* @return
*/
public ThreadPoolExecutor(int corePoolSize, 
                        int maximumPoolSize,
                        long keepAliveTime,
                        TimeUnit unit, 
                        BlockingQueue<Runnable> workQueue, 
                        RejectedExecutionHandler handler)

线程池的源码解读

1、ThreadPoolExecutor的execute()方法

public void execute(Runnable command) {
		if (command == null)
			throw new NullPointerException();
		//如果线程数大于等于基本线程数或者线程创建失败,将任务加入队列
		if (poolSize >= corePoolSize || !addIfUnderCorePoolSize(command)){
			//线程池处于运行状态并且加入队列成功
			if (runState == RUNNING && workQueue.offer(command)) {
				if (runState != RUNNING || poolSize == 0)
					ensureQueuedTaskHandled(command);
			}
			//线程池不处于运行状态或者加入队列失败,则创建线程(创建的是非核心线程)
			else if (!addIfUnderMaximumPoolSize(command)){
				//创建线程失败,则采取阻塞处理的方式
				reject(command); // is shutdown or saturated
			}
		}

	}

2、创建线程的方法:addIfUnderCorePoolSize(command)

private boolean addIfUnderCorePoolSize(Runnable firstTask) {
		Thread t = null;
		final ReentrantLock mainLock = this.mainLock;
		mainLock.lock();
		try {
			if (poolSize < corePoolSize && runState == RUNNING)
				t = addThread(firstTask);
		}finally {
			mainLock.unlock();
		}
		if (t == null)
			return false;
		t.start();
		return true;
	}

我们重点来看第7行,这里将线程封装成工作线程worker,并放入工作线程组里:

private Thread addThread(Runnable firstTask) {
		Worker w = new Worker(firstTask);
		Thread t = threadFactory.newThread(w);
		if (t != null) {
			w.thread = t;
			workers.add(w);
			int nt = ++poolSize;
			if (nt > largestPoolSize)
				largestPoolSize = nt;
		}
		return t;
	}

worker类的方法run方法,worker在执行完任务后,还会通过getTask方法循环获取工作队里里的任务来执行:

    public void run() {
        try {
            Runnable task = firstTask;
            firstTask = null;
            while (task != null || (task = getTask()) != null) {
                runTask(task);
                task = null;
            }
        } finally {
            workerDone(this);
        }
    }

由于线程池的饱和策略内容过多,我将重新记录一篇来讲Java提供的4中策略:
1、AbortPolicy:直接抛出异常
2、CallerRunsPolicy:只用调用所在的线程运行任务
3、DiscardOldestPolicy:丢弃队列里最近的一个任务,并执行当前任务。
4、DiscardPolicy:不处理,丢弃掉。

标签:面试题,多线程,--,对象,线程,内存,进程,command,null
From: https://www.cnblogs.com/lovexiao/p/16955975.html

相关文章

  • asp.net 2.0 中生成PDF
       近期要用asp.net2.0生成PDF,看了下书,查了下资料,发现可以有组件帮得上忙,可以下载itextsharp(​​https://sourceforge.net/projects/itextsharp​​​)下载,然后在工程......
  • go-dongle 0.2.0 版本发布了,一个轻量级、语义化的 golang 编码解码、加密解密库
    dongle是一个轻量级、语义化、对开发者友好的Golang编码解码和加密解密库Dongle已被awesome-go收录,如果您觉得不错,请给个star吧github.com/golang-module/dong......
  • String类常用方法
    String类概述概述java.lang.String类代表字符串。Java程序中所有的字符串文字(例如"abc")都可以被看作是实现此类的实例。类String中包括用于检查各个字符串的方法,比如......
  • 如何用vue+免费的webdb 实现一个世界杯足球竞猜系统
    一、前言最近世界杯在如火如荼的进行。我们都知道,中国也派出了我们的一支强大的队伍:中国建筑队,全程参与了世界杯的所有比赛。哈哈开个玩笑,不过说到世界杯,还真有不少朋友,不......
  • u-boot.lds:19: syntax error
    在移植中,使用u-boot-2013.04-rc1.tar.bz2移植到三星s3c6410芯片时会出现变异错误u-boot.lds:19:syntaxerrorgoogle后在maillist上知道smkd6400系列的已经不支持新......
  • XSD 字符串 数据类型概述
    字符串数据类型用于可包含字符串的值。字符串数据类型(StringDataType)字符串数据类型可包含字符、换行、回车以及制表符。下面是一个关于某个scheme中字符串声明的例子:<x......
  • canvas适配(图片、文字在移动端显示模糊问题)
    canvas图片、文字在移动端显示模糊问题因为canvas不是矢量图,而是像图片一样是位图模式的。高dpi显示设备意味着每平方英寸有更多的像素。也就是说二倍屏,浏览器就会以2......
  • 使用asu工具修改IBM服务器PN和SN
    0.条件准备:Windows电脑;电脑和IBM服务器带外IP可以正常网络通信;知道带外IP的账号和密码,IBM默认账号USERID密码PASSW0RD 1.在C盘目录下创建asu文件夹;2.将lnvgy_utl......
  • SPRD平台功耗调试分享
    一、关于底电流偏大的问题,这里总结一下一般的调试步骤1.如果底电流大于10ma以上的,首先需要抓串口log确定系统是否有睡眠,是否有外设一直在运行;从log中可以看有没有发生suspen......
  • D - Factorial and Multiple -- ATCODER
    D-FactorialandMultiplehttps://atcoder.jp/contests/abc280/tasks/abc280_d 思路    Codehttps://blog.csdn.net/wp_fxy/article/details/128179159h......