java线程
生命周期

New:线程正在创建
Runnable:线程可以运行(可能在等待时间片或正在运行)
Blocking:线程等待获取锁
Waiting:当前线程等待其他线程唤醒
Timed Waiting:当前线程等待一段时间后会自动醒来
Terminated:线程执行完毕或出现异常
线程接口
java中有三种线程的接口/类:
- Thread类
- Runnable接口
- Callable接口
使用
Thread
1 2 3 4 5 6 7 8 9
| public class MainApplication { public static void main(String[] args) { Thread thread = new Thread(() -> { System.out.println("线程执行"); }); thread.start(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12
| public class MainApplication extends Thread{ public static void main(String[] args) { MainApplication mainApplication = new MainApplication(); mainApplication.start(); }
@Override public void run() { System.out.println("线程执行"); } }
|
Runnable
1 2 3 4 5 6 7 8 9 10 11 12
| public class MainApplication implements Runnable{ public static void main(String[] args) { Thread thread = new Thread(new MainApplication()); thread.start(); }
@Override public void run() { System.out.println("线程执行"); } }
|
Callable
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| public class MainApplication implements Callable<Integer> { public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTask<Integer> futureTask = new FutureTask<>(new MainApplication()); Thread thread = new Thread(futureTask); thread.start(); System.out.println(futureTask.get()); }
@Override public Integer call() throws Exception { System.out.println("线程执行"); return 1; } }
|
API
静态方法
方法 |
说明 |
Thread.sleep() |
休眠当前正在执行的线程 |
Thread.yield() |
当前线程建议让出cpu,由调度器决定是否让出 |
|
|
实例方法
方法 |
说明 |
thread.setDaemon() |
true为设置线程为守护线程 |
thread.interrupt() |
中断在休眠中的线程,会抛出异常;在运行的线程则会设置标记,由线程自己决定是否中断 |
thread.interrupted() |
获取中断标记 |
thread.join() |
调用线程等待被调用线程执行完才会继续执行 |
object.wait() |
挂起线程,会释放锁,只能在同步代码块里调用 |
object.notify() |
随机唤醒线程,只能在同步代码块里调用 |
interrupt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| public class MainApplication extends Thread { public static void main(String[] args) { MainApplication mainApplication = new MainApplication(); mainApplication.start(); mainApplication.interrupt(); System.out.println("Main run"); }
@Override public void run() { try { Thread.sleep(2000); System.out.println("Thread run"); } catch (InterruptedException e) { e.printStackTrace(); } } }
|
interrupted
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| public class MainApplication extends Thread { public static void main(String[] args) throws InterruptedException { MainApplication mainApplication = new MainApplication(); mainApplication.start(); mainApplication.interrupt(); Thread.sleep(1000); System.out.println("Main run"); }
@Override public void run() { while (!interrupted()) {
} System.out.println("Thread run"); } }
|
线程互斥/协作
互斥方式
协作方式
- join()
- wait()、notify() / notifyAll()
- await()、single() / singleAll():在Condition上使用
线程池
对线程进行统一分配,调优和监控

ThreadPoolExecutor
一个线程集合workerSet和一个阻塞队列workQueue。当用户向线程池提交一个任务(也就是线程)时,线程池会先将任务放入workQueue中。workerSet中的线程会不断的从workQueue中获取线程然后执行。当workQueue中没有任务的时候,worker就会阻塞,直到队列中有任务了就取出来继续执行。

获取线程池状态api
方法 |
说明 |
threadPoolExecutor.getPoolSize() |
当前线程池中的线程数 |
threadPoolExecutor.getCorePoolSize() |
当前线程池中核心线程的数量 |
threadPoolExecutor.getActiveCount() |
正在执行任务的线程数 |
threadPoolExecutor.getCompletedTaskCount() |
已经完成的任务数 |
threadPoolExecutor.getTaskCount() |
线程池中已经提交的任务总数 |
threadPoolExecutor.isShutdown() |
线程是否已经调用了shutdown 方法 |
threadPoolExecutor.isTerminated() |
线程是否已经执行完任务并关闭 |
创建线程池的参数
1 2 3 4 5 6 7
| public ThreadPoolExecutor(int corePoolSize, // 核心线程数 int maximumPoolSize, // 允许的最大线程数=核心+非核心 long keepAliveTime, // 非核心存活时间 TimeUnit unit, // 存活时间单位 BlockingQueue<Runnable> workQueue, // 任务阻塞队列 RejectedExecutionHandler handler // 拒绝策略 )
|
任务阻塞队列种类:
ArrayBlockingQueue
: 基于数组结构的有界阻塞队列,按FIFO排序任
LinkedBlockingQueue
: 基于链表结构的阻塞队列,按FIFO排序任务,吞吐量通常要高于ArrayBlockingQueue;
SynchronousQueue
: 一个不存储元素的阻塞队列,每个插入操作必须等到另一个线程调用移除操作,否则插入操作一直处于阻塞状态,吞吐量通常要高于LinkedBlockingQueue;
PriorityBlockingQueue
: 具有优先级的无界阻塞队列;
拒绝策略种类:
AbortPolicy
: 直接抛出异常,默认策略;
CallerRunsPolicy
: 用调用者所在的线程来执行任务;
DiscardOldestPolicy
: 丢弃阻塞队列中靠最前的任务,并执行当前任务;
DiscardPolicy
: 直接丢弃任务
线程池状态
线程池中通过原子整数ctl
的前3位来记录线程池状态,后29位记录当前线程数

Executors
Executors把工作单元(Runnable)与执行机制分离开
通过Executors可以创建预设好参数的线程池,如固定大小线程池、只有救急线程的线程池等
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class MainApplication implements Runnable { public static void main(String[] args) { ExecutorService pool = Executors.newCachedThreadPool(); for (int i = 0; i < 5; i++) { pool.execute(new MainApplication()); } pool.shutdown(); }
@Override public void run() { System.out.println(Thread.currentThread().getName()); } }
|
api
方法 |
说明 |
pool.shutdown() |
等所有任务执行完成后关闭线程池 |
pool.shutdownNow() |
立即关闭线程池,所有线程执行interrupt() |
pool.submit() |
执行有返回值的任务 |
pool.execute() |
执行没有返回值的任务 |
为什么不建议使用Executor创建线程?
使用了无界队列,任务可以无限提交,会导致内存溢出;newCachedThreadPool
如果频繁创建销毁线程会导致大量的系统开销和内存溢出
Condition
相当于等待队列
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
| public class MainApplication { private Lock lock = new ReentrantLock(); private Condition condition = lock.newCondition();
public static void main(String[] args) throws InterruptedException { MainApplication mainApplication = new MainApplication(); ExecutorService pool = Executors.newFixedThreadPool(2); pool.execute(() -> mainApplication.before()); pool.execute(() -> mainApplication.after()); pool.shutdown(); }
public void before() { lock.lock(); try { condition.await(); } catch (InterruptedException e) { e.printStackTrace(); } finally { lock.unlock(); } System.out.println("before"); }
public void after() { lock.lock(); try { condition.signal(); } finally { lock.unlock(); } System.out.println("after"); } }
|