[笔记] Java基础(8)-多线程
1. 并行与并发
- 并行:多个任务同时执行
- 并发:多个任务在一定时间内同时发生,轮流切换执行
Java程序运行流程:JVM进程->主线程->main方法
2. 多线程实现方式
- 有两种方式,继承
Thread类或实现Runnable接口
- 继承
Thread类:new Thread() { public void run() { ... } }.start();
- 实现
Runnable接口:new Thread( new Runnable() { public void run() { ... } }).start();
- 区别:前者重写了
Thread类的run方法,start方法直接调用子类的run方法;后者Thread中的成员变量赋值为传入的Runnable对象,start方法调用Thread的run方法,run方法内部判断Runnable成员变量是否为空,不为空则调用Runnable对象的run方法;后者弥补了前者单继承的不足
3. Thread类
Thread类:java.lang.Thread
Thread():创建新的Thread对象
Thread(String name):创建新的Thread对象,线程名为name
Thread(Runnable target):创建新的Thread对象
Thread(Runnable target, String name):创建新的Thread对象,线程名为name
String getName():获取线程名;主线程默认为main,子线程默认为Thread-x
long getId():获取线程id
void setName():设置线程名
static Thread currentThread():获取当前线程对象
static void sleep(long millis):让当前线程休眠指定的毫秒值
void setDeamen(boolean on):将线程设置为守护线程
- 守护线程:当其它非守护线程执行完成后,守护线程自动退出
void join():等待该线程终止
void join(long millis):等待该线程执行指定的时间
static void yield():暂停当前线程,让CPU执行其它线程;效果不明显
void setPriority(int new):设置线程的优先级,范围1~10,默认为5;效果不明显
4. 线程同步
- 同步代码块
- 使用
synchronized关键字修饰的代码块,如:synchronized(lock) { ... }
lock为锁对象,相同锁对象的代码块不能同时执行;锁对象不能使用匿名对象,因为匿名对象不是同一个对象
- 同步方法
- 在返回值前使用
synchronized修饰的方法,分为静态方法与非静态方法
- 非静态方法锁对象为
this,如:public synchronized void fun() { ... }
- 静态方法的锁对象为当前类的字节码对象,如:
public static synchronized void fun() { ... }
- 死锁
DeadLock:多个线程同时抢占多个锁对象时,可能会产生死锁
Collections工具类中有synchronizedXX()方法,可将List、Set、Map变为线程安全的
5. Runtime类
Runtime类:java.lang.Runtime
- 该类使用单例模式实现
static Runtime getRuntime():获取当前运行时对象
Process exec(String command):在单独的进程中执行指定命令
6. Timer类
Timer类:java.util.Timer
Timer():创建新的计时器对象
void schedule(TimeTask task, Date time):在指定的时间执行指定的任务;到指定的时间会调用task对象的run方法;TimeTask为抽象类
void schedule(TimeTask task, Date time, long period):在指定的时间执行指定的任务,然后按period的毫秒值重复执行
void cancel():终止计时器,丢弃所有任务
7. Object类
Object类中定义了线程等待与唤醒方法
void wait():当前线程等待,直到其他线程调用此对象的notify方法;wait在哪里进入等待,唤醒后就从哪里开始执行;wait对象直接使用锁对象
void notify():唤醒在此对象监视器上的单个线程
void notifyAll():唤醒在此对象监视器上的所有线程
sleep与wait的区别:sleep在同步代码区域不会释放锁,wait会释放锁;sleep必须传入时间参数,wait可传可不传;sleep需要消耗CPU资源
8. ReentrantLock类
Reentrantlock类:java.util.concurrent.locks.ReentrantLock
- 该类为
JDK1.5之后加入
Reentrantlock():创建互斥锁对象
Codition newCondition():返回与该锁对象一起使用的Condition对象
Codition类:java.util.concurrent.locks.Condition
- 该类与
ReentrantLock类配合使用
void await():当前线程等待,直到其他线程调用signal方法
void signal():唤醒一个线程
void signalAll():唤醒所有线程
- 该类的方法与
Object类的wait、notify方法功能相似
- 通过
ReetrantLock对象的newCondition方法创建的Condition对象共同绑定同一个锁对象
9. ThreadGroup类
ThreadGroup类:java.lang.ThreadGroup
ThreadGroup(String name):创建新的线程组,名称为name
String getName():获取线程组的名称
void setDaemon(boolean daemon):设置组内线程的状态
- 通过
Thread对象的getThreadGroup方法可以获取该线程所属的线程组,默认线程都属于main线程组
10. 线程状态
- 共有五种状态:新建、就绪、运行、阻塞、死亡
- 新建:创建新的线程对象
- 就绪:有执行的资格,没有执行的权限
- 阻塞:没有执行的资格,没有执行的权限
- 运行:有执行的资格,有执行的权限
- 运行->就绪:
CPU资源被抢占
- 运行->阻塞:
sleep()、wait()
- 运行->死亡:
run()执行完、stop()
- 死亡:线程对象变成垃圾
11. 线程池
- 线程池:包含多个线程,线程执行完后并不会死亡,而会进入空闲状态
Executors类:java.util.concurrent.Executors
- 该类为
JDK1.5之后加入;为工程类,用于创建线程池
static ExecutorService newFixedThreadPool(int nThreads):创建包含nThreads个线程的线程池
static ExecutorService newSingleThreadExecutor():创建包含一个线程的线程池
ExecutorService接口:java.util.concurrent.ExecutorService
Future<?> submit(Runnable task):提交task执行
void shutdown():关闭线程池,此时线程池不会接受新任务,以前的任务还会继续执行
Future<T> submit(Callable<T> task):提交有返回值的任务执行
- 该方法会调用
task的call()方法
call()方法无参,故传参数需要使用构造方法
call()方法的返回值放在Future对象中,可以用get()方法获取
call()方法可以抛出异常