多线程
基本概念
- 进程:计算机在执行的程序的实体
- 线程:一个程序内部的顺序控制流
- 一个进程中可以包含一个或多个线程;一个线程就是一个程序内部的一条执行线索
- 每个进程有独立的代码和数据空间,进程的切换会有很大的的开销
- 同一类线程共享代码和数据空间,每个线程有独立运行的栈和程序计数器,线程切换的开销小
多线程实现的方式
- 创建线程类
- 继承Thread类
- 或实现Runnable接口
- 通过Thread类构造器来创建线程对象
- Thread()
- Thread(Runnable target)
- 通过start()方法激活线程对象
- 线程执行
1 | //线程类 |
2 | public class ThreadDemo extends Thread{ |
3 | public void run(){ |
4 | ...... |
5 | //执行的代码 |
6 | } |
7 | } |
8 | |
9 | //线程调用 |
10 | public class TestThread{ |
11 | ThreadDemo t1=new ThreadDemo(); |
12 | ThreadDemo t2=new ThreadDemo(); |
13 | t1.start(); |
14 | t2.start(); |
15 | ...... |
16 | } |
线程的声明周期
线程中的主要方法
线程的优先级
Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照线程的优先级来决定应调度哪个线程来执行。
有三个优先级:
让线程种植一段时间的静态方法,在睡眠期满的瞬间,再次调用该线程不一定会恢复他的执行。
1 | Thread.sleep(long millis) |
2 | //暂时停止执行millis毫秒 |
- join()
导致当前线程等待,直到调用这个join方法的线程终止
1 | join(); |
2 | join(long millis);等待执行millis毫秒 |
3 | join(long millis,int nanos);//等待执行millis毫秒,nanaos纳秒 |
- yield()
为其他可行的线程提供执行机会
静态方法——Thread.yield()
线程的中止
- 自动终止:一个线程完成执行后,不能再次执行
- 手动终止
- stop()——已经过时,基本不用
- interrupt()———粗暴的终止方式
- 可通过使用一个标志指示run方法退出,从而终止线程
线程的高级操作
1 | void wait() |
导致当前的线程等待,直到其他线程调用此对象的notify()方法或notiftAll()方法
1 | void notify() |
唤醒在此对象监视器上等待的单个线程
1 | void notifyAll() |
唤醒在此对象监视器上等待的所有线程
线程同步
为了确保两个线程在同时访问同一个文件的时,保证数据的一致性。
原理是:使用线程同步语句时,保证只有一个线程在执行。
锁
概念:每个对象都有一个锁标志,使用synchronized可与锁标志交互,保证里面的对象是线程同步的。
实现同步的两种方式
- synchronized方法
1 | synchronized void methodA(){ |
2 | |
3 | } |
- synchronized语句
1 | synchronized(Object object){ |
2 | ...... |
3 | //要同步的语句 |
4 | } |
注意:受到synchronized保护的程序代码块和方法中,要访问的对象属性必须设定为private,因为如果不设定为private,那么就可以用不同的方式来访问它,这样就达不到保护的效果了。
synchronized方法和synchronized语句的比较
synchronized方法
- 优点:可以具体知道哪些方法是被synchronized保护的。
- 缺点:方法中的有些内容不需要同步,会降低效率
synchronized语句 - 优点:可以专门针对某段代码,可以取得不同对象的锁。
- 缺点:无法明确得知哪些方法是被synchronized保护的。