1. 线程的基本概念
a. 线程:是一个程序内部的顺序控制流(一个程序的不同执行路径)。(class文件,exe文件--进程--静态概念)
b. 线程和进程的区别:
① 每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销。
② 线程可以看成是轻量级的进程,同一类线程共享代码和数据空间,每个线程有独立的运行栈和程序计数器(PC),线程切换的开销小。
③ 多进程:在操作系统中能同时运行多个任务(程序)。
④ 多线程:在同一应用程序中有多个顺序流同时执行。
c. Java 的线程是通过 java.lang.Thread 类来实现的。
d. 主线程:VM(虚拟机) 启动时会有一个由主方法(public static void main(){})所定义的线程。
e. 可以通过穿件 Thread 的实例来创建新的线程。
f. 每个线程都是通过某个特定 Thread 对象所对应的方法 run() 来完成其操作的,方法 run() 称为线程体。
g. 通过调用 Thead 类的 start() 方法来启动一个线程(若调用 run方法,则还在主线程中,执行完 run方法,才继续回到主线程)。
2. 线程的创建和启动
a. 可以有两种方式穿件新的线程:
① 第一种(推荐使用,能用接口不用继承):
⑴ 定义线程类,实现 Runnable 接口。
⑵ Thread myThread = new Thead(target) // target 为 Runnable 接口类型。
⑶ Runnable 中只有一个方法:
public void run(); // 用以定义线程运行体
⑷ 使用 Runnable 接口可以为多个线程提供共享数据。
⑸ 在实现 Runnable 接口的类的 run 方法定义中可以使用 Thread 的静态方法:
public static Thread currentThread() // 获取当前线程的引用
② 第二种(Thread 类本身也实现了 Runnable 接口):
⑴ 可以定义一个 Thread 的子类,并重写其 run 方法。如:
class MyThread extends Thead{
public void run() {...}
}
⑵ 然后生成该类的对象:
MyThread myThread = new MyThread(...)
3. 线程的调度和优先级
a. 线程的状态转换:
b. 线程控制基本方法:
⑴ isAlive() // 判断线程是否还“活”着,即线程是否还未终止。
⑵ getPriority() // 获得线程的优先级数值。
⑶ setPriority() // 设置线程的优先级数值。
⑷ Thread.sleep() // 当前线程睡眠指定毫秒数。
⑸ join() // 将当前线程与该线程“合并”,即等待该线程结束,再回复当前线程的运行。
⑹ yield() // 让出 CPU 当前线程进入就绪队列等待调度。
⑺ wait() // 当前线程进入对象的 wait pool。
⑻ notify() / notifyAll() // 唤醒对象的 wait pool 中的(一个 / 所有)等待的线程。
4. 线程的状态控制
a. sleep方法:
① 可以调用 Thread 的静态方法:
public static void sleep(long millis) throws InterruptedException //使得当前线程休眠(暂时停止执行 millis 毫秒,1000毫秒=1秒)
② 由于是静态方法,sleep 可以由类名直接调用:
Thread.sleep(...)
b. join方法:合并某个线程。
c. yield方法:让出CPU,给其他线程执行的机会(本身还会执行)。
d. interrupt() 方法:强制关闭线程(有try...catch...可执行)。
e. stop()方法:杀死线程(已废弃,直接杀死)。
f. 让线程停止的最好方法:在线程类内定义 flag ,将其改为 false 以结束 run方法内的 while(flag) 循环。
g. 线程的优先级(优先级越高,得到 CPU 时间片越多):
⑴ Java 提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程。线程调度器按照线程的优先级决定应调度哪个线程来执行。
⑵ 线程的优先级用数字表示,范围从 1 到 10,一个线程的缺省优先级是 5.
Thread.MIN_PRIORITY = 1
Thread.MAX_PRIORITY = 10
Thread.NORM_PRIORITY = 5
⑶ 使用下属线程方法获得或设置线程对象的优先级:
① int getPriority(); // 获得优先级
② void setPriority(int newPriority); // 设置优先级
5. 线程同步
a. 互斥锁:synchronized(this){...} (也可作为方法的修饰符,执行方法时,当前对象被锁定)// 锁定当前对象
b. 在JAVA语言中,引入了对象互斥锁的概念,保证共享数据操作的完整性。每个对象都对应于一个可称为“互斥锁”的标记,这个标记保证在任一时刻,只能有一个县城访问该对象。
c. 关键字:synchronized 来与对象的互斥锁联系。当某个对象被 synchronized 修饰时,表明该对象在任一时刻只能由一个线程访问。
① synchronized 的使用方法:
synchronized(this) {
num++;
try{Thread.sleep(1);}
catch(InterruptedException e){}
System.out.println(name+",你是第“+num+"个使用timer的线程");
}
② synchronized 还可以放在方法声明中,表示整个王法为同步方法:
synchronized public void add(String name) {...}
d. 死锁:A线程锁住a对象,访问b对象;同时,B线程锁住b对象,访问a对象。==> 出现死锁(解决办法之一:把锁的粒度加大,锁住一个包括a,b对象的对象即可)
e. synchronized 只锁定被修饰的方法内的语句(锁不住成员变量),其他方法仍可继续访问成员变量。即:只保证同一时刻只有一个线程访问被修饰的语句,不保证访问同一资源的其他方法。(解决办法:锁住所有访问同一资源的方法。前一个方法已锁定,后一个方法必须等前一方法执行完才可再锁定)