- 进程:自己独有内存空间,操作系统级别同时运行多个任务,每个任务相当是一个应用程序。进程间切换很耗时
- 线程:是运行在进程上的,一个进程可以运行多个线程,线程共享同一段内存区域。线程间切换很快,一个进程中至少有一个线程在运行。
时间片长短不一定,分配给哪些线程也不一定。
thread每一个类描述一个线程
run方法定义线程要完成的任务
start方法用于启动线程,使其可以并发运行
如果两个任务运行是有先后顺序的,我们称为同步的。
如果是各自做各自的,我们称为异步的。
同步一般发生在同一线程中,异步是在多线程中完成。
使用Runnable的好处
- 降低耦合
- 可以实现多继承
Thread current = Thread.currentThread();
用于获取运行当前代码片段的线程
当程序运行起来是,OS会启动一个进程来运行JVM
而进程启动后会创建一个线程,用这个线程来运行main方法
long getID() 返回该线程的标识符
String getName() 返回线程的名称
int getPriority() 返回线程的优先级,默认是5
Thread.state.getState() 返回线程的状态
boolean isAlive() 测试线程是否处于活动状态
boolean isDaemon() 测试线程是否为守护线程
boolean isInterrupted() 测试线程是否已经中断
void setPriority(int priority)设置线程优先级
守护线程也叫后台线程
void setDaemon(boolean)当为true时该线程为守护线程
进程中,所有前台线程结束,守护线程强制结束
GC就是运行中守护线程上的
static void sleep(long ms)
用于使当前线程进入阻塞状态,阻塞时间到了,使线程进入Runnable状态,并非Running状态,所以可能存在误差
static void yield() 用于当前线程主动让出CPU时间片回到Runnable状态
void join() 用于等待当前线程结束
多线程并发访问同一数据时,会产生线程安全问题
解决办法就是把异步操作变为同步操作
被synchronized修饰的方法被称为同步方法
synchronize块用于同步某一代码片段的,通常范围小于修饰方法
当一个类中,多个方法被synchronized修饰时,这些方法就是互斥的,多个方法不允许同时执行
同步代码块
synchronized(同步监视器-锁对象引用){
//代码块
}
使用同步块可以缩小同步范围,提升并发效率,所对象通常是this
静态方法锁
public synchronized static void xxx(){……}
静态方法上锁后,同步是跨对象的。
wait:在当前对象上阻塞
notify:调用对象的notify方法,可以该对象上等待的线程解除阻塞
try {
//在Object对象上等待
synchronized (object) {
/*
* wait方法要求
* 调用那个对象的wait方法就要将该对象加锁
*/
object.wait();//wait是无限期等待
}
} catch (InterruptedException e) {
e.printStackTrace();
}
Collections可以将集合转换为线程安全的
线程池:
控制线程数量
重用线程
Executors.newCachedThreadPool() 根据需求创建线程,弹性好
Executor.newFixedThreadPool(int NThreads) 固定大小线程池
Executors.newScheduledThreadPoll(int corePoolSize) 可延迟运行任务
Executors.newSingleThreadExecutor() 单worker线程池
BlockingQueqe 双缓冲队列,存取可以异步,存取本身还是同步的
ArrayBlockingQueue 规定大小的BlockingDuque,指明大小
LinkedBlockingQueue 不定长的BlockingDuque,可规定大小
PoriorityBlockingDuque 规定大小,谁小出谁
SynchronizeQueue,只能放一个元素,放取交替进行