笔记关键字:Java 多线程 线程创建方式 线程的生命周期 线程常用方法 线程池
如下述内容有误,还请及时告知,感谢
一、线程的创建方式
1. 继承 Thread 类
优点:编写简单,直接用 this 可获得当前线程
缺点:线程类继承了 Thread 类,无法再继承其他类
// 一个类继承 Thread 类,重写 run() 方法
public class Thread01 extends Thread{
@Override
public void run() {
System.out.println(this.getName());
}
}
//创建 MyThread 的实例,调用实例的 start() 方法启动线程
public class Test01 {
public static void main(String[] args) {
Thread01 td = new Thread01();
td.setName("线程 1");
td.start();
}
}
2. 实现 Runnable 接口
优点:可以继承其他类,避免了单继承的局限性,更为灵活
缺点:编写较为复杂,获得当前线程需要使用 Thread.currentThread() 方法
//创建一个类并实现 Runnable 接口,重写 run() 方法
public class Thread02 implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
public class Test02 {
public static void main(String[] args) {
Thread02 tr = new Thread02();
Thread td = new Thread(tr,"线程 2");
td.start();
}
}
3. 实现 Callable 接口
优点:有返回值,可抛出异常,避免单继承的局限性
缺点:实现较复杂
public class Thread03 implements Callable {
@Override
public Object call() throws Exception {
//返回当前线程的名称
return Thread.currentThread().getName();
}
}
public class Test03 {
public static void main(String[] args) throws Exception {
Thread03 tc = new Thread03();
FutureTask futureTask = new FutureTask(tc);
Thread td = new Thread(futureTask,"线程 3");
td.start();
//获得线程执行完的返回值
Object result = futureTask.get();
System.out.println("线程返回值为:"+result);
}
}
二、线程的状态(生命周期)
Java 线程的生命周期.png
三、线程常用方法
线程的常用方法包含在 Thread 类中和 Object 类中
- Object 类中的方法
方法名 | 作用 |
---|---|
wait() | 使当前线程等待(释放锁,释放 CPU 资源),直到另一个线程调用该对象notify()方法或notifyAll()方法 |
notify() | 唤醒正在等待对象监视器的单个线程,如果有多个正在等待的线程,随机唤醒其中一个 |
notifyAll() | 唤醒正在等待对象监视器的所有线程 |
- Thread 类中的方法
方法名 | 作用 |
---|---|
sleep(long millis) | 线程休眠(不释放锁,释放 CPU 资源) |
join() | 让“主线程”等待“子线程”结束之后才能继续运行 |
join(long millis) | 等待这个线程死亡最多 millis毫秒 |
yield | 线程让步,把运行的线程转为就绪状态,重新抢CPU执行权 |
interrupt() | 中断这个线程 |
interrupted() | 测试当前线程是否中断 |
getId | 返回线程ID,每个线程都有唯一的ID |
getState | 返回线程状态 |
getName() | 返回线程名称 |
setName | 设置线程名称 |
setPriority(int newPriority) | 更改线程优先级,线程优先级越高,获得CPU执行权的机率越大 |
getPriority() | 返回此线程的优先级 |
setDaemon(boolean on) | 将此线程标记为 daemon线程或用户线程 |
isDaemon() | 测试这个线程是否是守护线程 |
isAlive() | 测试这个线程是否活着 |
四、线程池 Executors
避免频繁的创建销毁,资源重复利用(提高响应速度,降低资源消耗),还可统一管理
public class Thread04 implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}
public class Test04 {
public static void main(String[] args) {
ThreadPoolExecutor pool =
new ThreadPoolExecutor(2,4,1000, TimeUnit.MINUTES, new LinkedBlockingQueue<Runnable>(), Executors.defaultThreadFactory());
pool.submit(new Thread04());
pool.submit(new Thread04());
pool.submit(new Thread04());
pool.submit(new Thread04());
pool.submit(new Thread04());
pool.shutdown();
}
}
相关参数
参数名 | 说明 |
---|---|
int corePoolSize | 核心线程池大小 |
int maximumPoolSize | 最大线程池大小 |
long keepAliveTime | 当线程池中空闲线程数量超过corePoolSize时,多余的线程会在多长时间内被销毁 |
TimeUnit unit | keepAliveTime时间单位 |
BlockingQueue<Runnable> workQueue | 阻塞任务队列 |
ThreadFactory threadFactory | 线程工厂,用于创建线程 |
RejectedExecutionHandler handler | 拒绝策略,当提交任务数超过maximumPoolSize、workQueue之和时,任务会交给RejectedExecutionHandler来处理 |
阻塞任务队列 workQueue
- ArrayBlockingQueue :
- LinkedBlockingQueue :
- PriorityBlockingQueue :
- SynchronousQueue :
拒绝策略 handler
- AbortPolicy :该策略直接抛出异常,阻止系统工作;
- CallerRunsPolicy :如果线程池的线程数量达到上限,该策略会把任务队列中的任务放在调用者线程当中运行;
- DiscardOldestPolicy :该策略会丢弃任务队列中最老的一个任务,也就是当前任务队列中最先被添加进去的,马上要被执行的那个任务,并尝试再次提交;
- DiscardPolicy :该策略会默默丢弃无法处理的任务;
未完待续......