Java并发编程教程--并发基础(三
3.5常见方法
方法名 | static | 功能说明 | 注意 |
---|---|---|---|
start() | 启动一个新线程,在新的线程运行run方法中的代码 | start 方法只能是让线程进入就绪,里面的代码不一定立刻运行(CPU的时间片还没有分给它),每个线程对象的start方法只能调用一次,如果调用多次会出现IlleagleThreadStateException | |
run() | 新线程启动后会调用的方法 | 如果在构造Thread对象时传递了Runnable参数,则线程启动后会调用Runnable中的run方法,否则默认不执行任何操作.但是可以创建Thread的子类对象,来覆盖默认行为 | |
join() | 等待线程运行结束 | ||
join(long n) | 等待线程运行结束,最多等待n毫秒 | ||
getId() | 获取线程长整型的id唯一 | id唯一 | |
getName() | 获取线程名 | ||
setName() | 修改线程名 | ||
getPriority() | 获取线程优先级 | ||
setPriority() | 修改线程优先级 | Java中规定线程的优先级是1~10的整数,较大的优先级能提高该线程被CPU调度的几率 | |
getState() | 获取线程状态 | Java中线程状态是用6个enum表示,分别为NEW,RUNNABLE,BLOCKED,WAITING,TIMED_WAITING,TERMINATED | |
isInterrupted() | 判断是否被打断 | 不会清楚打断标记 | |
isAlive() | 线程是否存活(还没有运行完毕) | ||
interrupt() | 打断线程 | 如果被打断线程正在sleep,wait,join会导致被打断的线程抛出InterruptedException,并清除打断标记,如果打断的正在运行的线程,则会设置打断标志,park的线程被打断,也会设置打断标记 | |
interrupted() | static | 判断当前线程是否被打断 | 会清除 打断标记 |
currentThread() | static | 获取当前正在执行的线程 | |
sleep(long n) | static | 让当前执行的线程休眠n毫秒,休眠时让出CPU的时间片给其他线程 | |
yield() | static | 提示线程调度器让出当前线程对CPU的使用 | 主要是为了测试和调试 |
3.6 start与run
Java的线程是通过java.lang.Thread类来实现的。VM启动时会有一个由主方法所定义的线程。可以通过创建Thread的实例来创建新的线程。每个线程都是通过某个特定Thread对象所对应的方法run()来完成其操作的,方法run()称为线程体。通过调用Thread类的start()方法来启动一个线程。
3.7 sleep与yield
sleep
1.调用sleep会让当前线程从Running进入Timed Waiting状态
2.其他线程可以使用interrupt方法打断正在睡眠的线程,这时sleep方法会抛出InterruptedException
3.睡眠结束后的线程未必会立刻得到执行
4.建议使用TimeUtil的sleep替代Thread的sleep来获得更好的可读性.
yield
1.调用yield会让当前线程从Running 进入 Runnable状态,然后调度执行其他同优先级的线程.如果这时没有同优先级的线程,那么不能保证让当前线程暂停的效果
2.具体的实现依赖于操作系统的任务调度器
线程优先级
- 线程优先级会提示调度器优先调度该线程,但是它仅仅是一个提示,调度器可以忽略它
- 如果CPU比较忙,那么优先级高的线程会获得更多的时间片,但CPU闲时,优先级几乎没有作用
案例-防止CPU占用率100%
Sleep实现
在没有利用CPU来计算时,不要让while(true)空转浪费CPU,这时可以使用yield或者sleep来让出cpu的使用权给其他程序
while(true){
try{
Thread.sleep(50);
}catch (InterruptedException e) {
e.printStackTrace();
}
}
- 可以用wait或者条件变量达到类似的效果
- 不同的是,后两种都需要加锁,并且需要相应的唤醒操作,一般适用于需要进行同步的场景
- sleep适用于无需锁同步的场景
wait实现
synchronized(锁对象) {
while(条件不满足 )
}
3.8 Join方法详解
public class Test10 {
static int r =0;
public static void main(String[] args) throws InterruputedException {
test1();
}
private static void test1() throws InterruptedException {
log.debug("开始");
Thread t1 = new Thread(()->{
log.debug("开始");
sleep(1);
log.debug("结束");
r = 10;
},"t1");
}
t1.start();
log.debug("结果为:{}",r);
log.debug("结果") }
分析:
- 因为主线程和线程t1是并行执行的,t1需要1秒之后才能算出r =10;
- 而主线程一开始就要打印r的结果,所以只能打印出r=0
解决方法
- 用sleep行不行?为什么?
- 用join ,加在t1.start()之后即可