概述
- 线程是进程的一个执行单元,是CPU任务调度的基本单位。一个进程可以包含多个线程,同一个进程下的所有线程共享改进程的所有资源
生命周期
新建状态:创建实例
就绪状态:等待CPU分配时间
运行状态:执行中,获得CPU资源。
阻塞状态:释放cpu资源,在某些条件下回到就绪状态,调用sleep方法进入阻塞状态,释放cpu资源,不会释放锁,调用wait方法,在释放资源的同时,也会释放锁。
死亡状态:线程执行完毕,或者stop线程。
优点
- 划分尺度小,执行开销小,提高并行效率
- 共享内存,提高资源利用率和执行效率
缺点
- 没有单独的地址空间,不能独立运行,无法对资源进行管理。
创建
创建线程的四种方式:
-
继承Thread类
public class ThreadDemo extends Thread {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
System.out.println("创建线程的第一种方式");
}
}
ThreadDemo threadDemo = new ThreadDemo();
threadDemo.setName("thread-demo");
//1标准的启动方式
threadDemo.start();
//2、调用类的方法的启动方式
threadDemo.run();
start()和run()的区别:
start()方法会创建一个新的线程,执行run方法。
run()方法,类的方法调用是在主线程上执行。
可通过在Thread.currentThread().getName()查看执行线程名
-
继承runable接口
public class RunableDemo implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
System.out.println("创建线程的第二种方法");
}
}
Thread thread = new Thread(new RunableDemo());
thread.start();
推荐使用这种方式,有利于在多继承的情况下的代码扩展
-
有返回值的创建线程的callable方式
public class CallableDemo implements Callable {
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName());
System.out.println("创建线程的第二种方法");
return 1;
}
}
CallableDemo callableDemo = new CallableDemo();
FutureTask futureTask = new FutureTask(callableDemo);
Thread callThread = new Thread(futureTask,"返回值");
callThread.start();
futureTask.get();
以继承callable接口创建线程,可以有返回值,通过cas原理把数据set到futureTask对象中,调用get方式会使程序进入阻塞状态,直到线程执行完毕拿到返回值。
-
线程池
- 顶层接口Executor,内部包含一个execute方法,入参是个Runable对象。
- ThreadPoolExecutor,线程池定义类
* corePoolSize 核心线程数
* maximumPoolSize 最大线程数
* keepAliveTime 空闲时间
* unit 单位
* workQueue 工作队列,用于管理任务
* threadFactory 线程工厂类
* defaultHandler 默认处理方法,工作队列无空闲的情况下的处理办法。 - Executors 创建线程池的工具类,tips:工具类一般都是以s结尾,例:Collections、Arrays
线程池种类
- 单一线程执行任务,FIFO机制,保证任务的有序性,线程池核心线程和最大线程数均为1,永不过期,以一个链表队列管理任务有序执行。源码结构:
public static ExecutorService newSingleThreadExecutor() {
return new FinalizableDelegatedExecutorService
(new ThreadPoolExecutor(1, 1,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>()));
}
- 固定大小的线程池,当有新的任务进来,就会创建一个新的线程去执行,任务执行完毕,线程并不会被回收,而是变成空闲线程,等待执行下次任务,会占用一部分资源,但是节约了线程重复创建和销毁的开销。
public static ExecutorService newFixedThreadPool(int nThreads) {
return new ThreadPoolExecutor(nThreads, nThreads,
0L, TimeUnit.MILLISECONDS,
new LinkedBlockingQueue<Runnable>());
}
- 不固定大小的线程池,创建线程最大数为Integer.MAX_VALUE,而且可以回收空闲线程。
public static ExecutorService newCachedThreadPool() {
return new ThreadPoolExecutor(0, Integer.MAX_VALUE,
60L, TimeUnit.SECONDS,
new SynchronousQueue<Runnable>());
}
- 定时任务线程,定时任务,支持周期性工作。
public ScheduledThreadPoolExecutor(int corePoolSize) {
super(corePoolSize, Integer.MAX_VALUE, 0, NANOSECONDS,
new DelayedWorkQueue());
}