线程:
- 线程实现的方式?
1)继承Thread类,重写Thread类的run方法
2)实现Runnable接口,重写Rnnnable接口的run方法
3)创建线程池
- 线程的状态?
NEW: 新建 RUNNABLE: (就绪)运行 BLOCKED: 阻塞 WAITING: 死死等待 TIMED_WAITING: 超时等待 TERMINATED: 终止状态
- 线程与进程的区别?
进程:是正在运行的客户端程序,能够调用系统资源的独立单位 线程:是依赖于进程存在的,一个进程可能存在多个线程, 线程是能够执行的独立的单元,一个线程就相当于进程中的某个任务
- 线程之间如何同步数据?
1)同步方法,使用synchronized关键字,可以修饰普通方法、静态方法,以及语句块。 2)同步代码块,用synchronized关键字修饰语句块。 被该关键字修饰的语句块会自动被加上内置锁,从而实现同步. 3)使用特殊域变量(volatile)实现线程同步。 4)使用局部变量实现线程同步.如果使用ThreadLocal管理变量,则每一个使用该变量的线程都获得该变量的副本, 副本之间相互独立,这样每一个线程都可以随意修改自己的变量副本,而不会对其他线程产生影响。
- 线程池有哪些种类?
1.newCachedThreadPool 创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程。 2.newFixedThreadPool 创建一个指定工作线程数量的线程池。每当提交一个任务就创建一个工作线程, 如果工作线程数量达到线程池初始的最大数,则将提交的任务存入到池队列中。 3.newSingleThreadExecutor 创建一个单线程化的Executor,即只创建唯一的工作者线程来执行任务, 它只会用唯一的工作线程来执行任务,保证所有任务按照指定顺序执行。 如果这个线程异常结束,会有另一个取代它,保证顺序执行。 单工作线程最大的特点是可保证顺序地执行各个任务,并且在任意给定的时间不会有多个线程是活动的。 4.newScheduleThreadPool 创建一个定长的线程池,而且支持定时的以及周期性的任务执行,支持定时及周期性任务执行。 5.newSingleThreadScheduledExecutor 创建一个单线程执行程序,它可安排在给定延迟后运行命令或者定期地执行。 线程池中最多执行1个线程,之后提交的线程活动将会排在队列中以此执行 并且可定时或者延迟执行线程活动。
- 线程池的7大参数是?
1、corePoolSize 线程池核心线程大小 线程池中会维护一个最小的线程数量,即使这些线程处理空闲状态,他们也不会被销毁,除非设置了allowCoreThreadTimeOut。 这里的最小线程数量即是corePoolSize。 2、maximumPoolSize 线程池最大线程数量 一个任务被提交到线程池后,首先会缓存到工作队列中, 如果工作队列满了,则会创建一个新线程, 然后从工作队列中的取出一个任务交由新线程来处理,而将刚提交的任务放入工作队列。 线程池不会无限制的去创建新线程,它会有一个最大线程数量的限制, 这个数量即由maximunPoolSize来指定。 3、keepAliveTime 空闲线程存活时间 一个线程如果处于空闲状态,并且当前的线程数量大于corePoolSize, 那么在指定时间后,这个空闲线程会被销毁,这里的指定时间由keepAliveTime来设定 4、unit 空间线程存活时间单位 keepAliveTime的计量单位 5、workQueue 工作队列 新任务被提交后,会先进入到此工作队列中,任务调度时再从队列中取出任务。 jdk中提供了四种工作队列: ①ArrayBlockingQueue 基于数组的有界阻塞队列,新任务进来后,会放到该队列的队尾, 有界的数组可以防止资源耗尽问题。 当线程池中线程数量达到corePoolSize后,再有新任务进来, 则会将任务放入该队列的队尾,等待被调度。 如果队列已经是满的,则创建一个新线程, 如果线程数量已经达到maxPoolSize,则会执行拒绝策略。 ②LinkedBlockingQuene 基于链表的无界阻塞队列(其实最大容量为Interger.MAX),按照FIFO排序。 由于该队列的近似无界性,当线程池中线程数量达到corePoolSize后, 再有新任务进来,会一直存入该队列,而不会去创建新线程直到maxPoolSize, 因此使用该工作队列时,参数maxPoolSize其实是不起作用的。 ③SynchronousQuene 一个不缓存任务的阻塞队列,生产者放入一个任务必须等到消费者取出这个任务。 也就是说新任务进来时,不会缓存,而是直接被调度执行该任务, 如果没有可用线程,则创建新线程,如果线程数量达到maxPoolSize,则执行拒绝策略。 ④PriorityBlockingQueue 具有优先级的无界阻塞队列,优先级通过参数Comparator实现。 6、threadFactory 线程工厂 创建一个新线程时使用的工厂,可以用来设定线程名、是否为daemon线程等等 7、handler 拒绝策略 当工作队列中的任务已到达最大限制,并且线程池中的线程数量也达到最大限制, 这时如果有新任务提交进来,就需要用到拒绝策略, jdk中提供了4种拒绝策略: ①CallerRunsPolicy 该策略下,在调用者线程中直接执行被拒绝任务的run方法, 除非线程池已经关闭,则直接抛弃任务。 ②AbortPolicy 该策略下,直接丢弃任务,并抛出RejectedExecutionException异常。 ③DiscardPolicy 该策略下,直接丢弃任务,什么都不做。 ④DiscardOldestPolicy 该策略下,抛弃进入队列最早的那个任务,然后尝试把这次拒绝的任务放入队列
- Java 中的 volatile 关键是什么作用?怎样使用它?在 Java 中它跟 synchronized 方法有什么不同?
volatile是线程同步的轻量级实现 它的作用:保证可见性 保证有序性 区别: 1. volatile:只能修饰共享变量(即成员变量),不可修饰方法和方法中的局部变量。 synchronized:可以修饰在代码块、方法、静态方法。 2. 多线程访问volatile不会发生阻塞,而synchronized会出现阻塞; 3. volatile能保证数据的可见性,但不能保证原子性; synchronized可以保证原子性,也可以间接保证可见性,因为他会将私有内存和公共内存中的数据同步。 4. volatile解决的是变量在多个线程之间的可见性; synchronized关键字解决的是多个线程之间访问资源的同步性。
- 你在多线程环境中遇到的常见的问题是什么?你是怎么解决它的?
在多线程环境下产生了死锁问题 解决方法: 线程每次只锁定一个对象并且在锁定该对象的过程中不再去锁定其他的对象
- 启动线程方法 start和 run有什么区别?
当程序调用start()方法,将会创建一个新线程去执行run()方法中的代码。 如果直接调用run()方法的话,会直接在当前线程中执行run()中的代码, 不会创建新线程。就像一个普通方法一样。 当一个线程启动之后,不能重复调用start(),但是可以重复调用run()方法。
- 什么是阻塞式方法?
阻塞式方法是指程序会一直等待该方法完成期间不做其他事情,程序一直停在read()方法这里,等待数据。 没有数据就不继续往下执行,直到得到数据。 ServerSocket 的accept()方法就是一直等待客户端连接。 这里的阻塞是指调用结果返回之前,当前线程会被挂起,直到得到结果之后才会返回。 此外,还有异步和非阻塞式方法在任务完成前就返回。



