一、线程
Thread中的方法解释
1.join()
void join():等待线程终止
void join(long millis):等待该线程终止的最长等待时间是millis毫秒
void join(long millis, int nanos):等待该线程结束的最长等待时间是millis毫秒+nanos纳秒
2.sleep()方法
void sleep(long millis):在指定的毫秒数内让正在执行的线程休眠,此操作受到系统计时器和调度程序精度和准确性的影响。
void sleep(long millis, int nanos)与join类似
sleep(long)使当前进程进入停滞状态,所以sleep()的线程在指定时间内不会被执行。
sleep(long)是不会释放锁的
3.yield()方法
public static void yield()暂停当前正在执行的线程对象,使其进入不可运行状态,这段时间的长短是由程序设定的,yield方法使当前线程让出CPU的占有权,但是让出的时间是不可设定的。并执行其他线程
只会提供相同或者更高优先级的线程运行,不推荐使用
4 wait(): wait()是Object类中的方法,而sleep()是Thread类提供的方法
sleep没有释放锁,使得线程仍然可以同步控制,sleep不会让出系统资源
而wait是进入线程池中等待,让出系统资源。
线程的简单实例:
现在有T1、T2、T3三个线程,你怎样保证T2在T1执行完后执行,T3在T2执行完后执行?
答:线程类Thread中提供了join()方法,该方法的意义是等待线程执行完毕的意思,因此只需要调用join()方法即可,具体代码如下:
public class ThreadTest {
public static void main(String [] args){
method01();
}
private static void method01() {
final Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("t1 is Running");
}
});
final Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t2 is Running");
}
});
Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t3 is Running");
}
});
t1.start();
t2.start();
t3.start();
}
}
二、线程池
1.使用线程池的原因和好处
原因:
1)线程的创建和销毁都需要时间,当有大量的线程创建和销毁时,那么这些时间的消耗比较明显,导致应用性能的下降。
2)大量的线程创建,执行和销毁非常的消耗CPU和内存,这样将直接影响系统的吞吐量,导致性能的急剧下降,如果内存占用较多甚至会造成OOM
3)大量的线程的创建很容易导致GC频繁的执行,进而产生内存抖动的现象,进而造成界面卡顿。
好处
1)减少在创建和销毁线程上所花的时间以及系统的开销
2)如果不使用线程池,有可能造成系统创建大量的线程而导致消耗完系统内存以及“过度切换”
2.线程池的使用场景
1)在项目中需要频繁的开启线程,需要多线程去处理不同的任务
2)需要监控线程的运行状态
3.线程池遵循的运行规则
1)如果线程池中的数量为达到核心线程的数量,则直接启动一个核心线程来执行任务
2)如果线程池的数量已经达到或者超过核心线程的数量,则任务会被插入到任务队列进行等待。
3)如果(2)中的任务无法插入到任务队列中,由于任务队列已满,这时候如果线程数量未达到线程池规定的最大值,则会启动一个非核心线程来执行任务。
4)如果(3)中线程数量已经达到了线程池最大值,则会拒绝执行此任务,ThreadPooExector会调用RejectedExecutionHandler的rejectedExection方法通知调用者。
4.ThreadPoolExecutor
ThreadPoolExecutor :线程池,它实现了ExecutorService接口,并封装了一系列的api是的它具有线程池的特性,其中包括工作队列,核心线程数以及最大线程数等等。
线程池的种类:
1)newFixedThreadPool作用
返回一个固定线程数的线程池,该线程池中的线程数量始终保持不变,既不会再创建新的线程,也不会销毁已经创建好的线程,自始至终都是那几个固定线程在工作,因此该线程池可以控制线程的最大并发数;
例子如果有一个新的任务提交时,如果线程池中有多余的线程则会使用空闲线程处理任务,如果没有,则会把这个新任务添加到一个任务队列椎间盘买个,一旦线程空闲时,则按照FIFO方法处理任务队列中的任务数。
2)newCachedThreadPool()作用
返回一个可以根据实际情况调整线程池中线程数量的线程池。既该线程池中的线程数量不确定,是根据实际情况调整的。
如果该线程池中的所有线程都在工作,则此时有新的任务提交,则将会创建新的线程去提交,而假设之前有一些线程完成了任务,现在又有了新任务提交,则将不会创建新的线程,而是复用空闲的线程去处理任务,但是同时会设置空闲时间,如果该线程超过了空闲时间,则会被回收。
3)newSingleThreadExecutor()
该方法返回一个只有一个线程的线程池,既每次只能执行一个线程任务,多余的任务会保存到一个任务队列中,等待这一个线程空闲,当这个线程空闲后按照FIFO的方式执行任务队列中的任务。
4)newScheduledThreadPool
返回一个可以控制线程池内线程定时或者周期性执行某任务的线程池
5)newSingleThreadScheduledExecutor
返回一个可以控制线程池内线程定时或周期行执行某任务的线程池。只不过和上面的区别是该线程池的大小为1,而上面的可以指定线程池的大小。
网友评论