image.png
setPriority(int newPriority) 更改线程的优先级;
static void sleep(long milis)
void join() 插队,等待该线程终止
static void yield() 暂停当前正在执行的线程对象,并执行其他线程
boolean isAlive() 测试线程是否处于活动状态
停止线程
image.png
public class StopDemo implements Runnable{
public static void main(String[] args) {
StopDemo stopDemo = new StopDemo();
new Thread(stopDemo).start();
for (int i = 0; i < 1000; i++) {
System.out.println("thread----main"+i);
if(i == 500){
stopDemo.stop();
System.out.println("停掉子线程--------");
}
}
}
private boolean flag = true;
@Override
public void run() {
while (flag){
System.out.println("thread----run");
}
}
public void stop(){
this.flag = false;
}
}
线程休眠
image.png
/*
模拟计时器
*/
public class SleepDemo implements Runnable {
@Override
public void run() {
try {
Date nowDate = new Date();
while (true){
Thread.sleep(1000);
System.out.println(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(nowDate));
nowDate = new Date();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
SleepDemo sleepDemo = new SleepDemo();
new Thread(sleepDemo).start();
}
}
线程礼让
image.png
/*
线程礼让,回到同一起跑线,重新等待 CPU 调度,可能不成功。
*/
public class YieldDemo {
public static void main(String[] args) {
MyYield myYield = new MyYield();
new Thread(myYield,"a").start();
new Thread(myYield,"b").start();
}
}
class MyYield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程开始了");
Thread.yield();
System.out.println(Thread.currentThread().getName()+"线程结束了");
}
}
线程插队 join
合并线程,待此线程执行完毕后,再执行其他线程,其他线程阻塞。
public class JoinDemo implements Runnable {
@Override
public void run() {
for (int i = 0; i < 1000; i++) {
System.out.println("VIP 线程来了"+i);
}
}
public static void main(String[] args) {
Thread thread = new Thread(new JoinDemo());
thread.start();
for (int i = 0; i < 200; i++) {
System.out.println("主线程执行中"+i);
if(i==100){
try {
thread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
观察线程状态
public class WatchStateDemo {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(()->{
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("..........");
});
Thread.State state = thread.getState();
System.out.println(state);//NEW
thread.start();
state = thread.getState();
System.out.println(state);//RUNNABLE
while (thread.getState() != Thread.State.TERMINATED){
Thread.sleep(150);
state = thread.getState();
System.out.println(state);//TIMED_WAITING 最后TERMINATED
}
}
}
线程优先级
image.png
守护线程
image.png
public class deamonDemo {
public static void main(String[] args) {
Deamon deamon = new Deamon();
Person person = new Person();
Thread deamonThread = new Thread(deamon);
deamonThread.setDaemon(true);
deamonThread.start();
Thread personThread = new Thread(person);
personThread.start();
}
}
class Person implements Runnable{
@Override
public void run() {
for (int i = 0; i < 36500; i++) {
System.out.println("每天愉快的活着");
}
System.out.println("===========goodbye world=============");
}
}
class Deamon implements Runnable{
@Override
public void run() {
while (true){
System.out.println("上帝保有着你");
}
}
}
sleep 与 yield
sleep
- 当前线程从 Running 进入 Timed Waiting 状态(阻塞)
- 其他线程可以使用 interrupt 方法 打断正在睡眠的线程,这是 sleep 方法会抛出 InterruptedException
- 睡眠结束后的线程未必会立即执行
- 建议使用 TimeUnit 的 sleep 代替 Thread.sleep 获取更好的可读性
yield - 当前线程从 Running 进入 Runnable 就绪状态
- 具体的实现依赖于操作系统的任务调度器
/**
* 线程被打断
*/
public class InterruptDemo {
public static void main(String[] args) {
Thread t1 = new Thread() {
@Override
public void run() {
try {
System.out.println("t1 enter sleep^");
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
System.out.println("t1 is waked up");
e.printStackTrace();
}
System.out.println("t1 被唤醒了");
}
};
t1.start();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
t1.interrupt();
System.out.println("main 继续执行……");
}
}
案例--防止 CPU 占用100%
在没有利用CPU计算时,不要让 while(true)空转
while (true){
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
- 可以用 wait 或 条件变量达到类似效果
- 不同的是,后两种都需要加锁,并且需要相应的唤醒操作,一般适用于要进行同步的场景
- sleep 适用于无需锁同步的场景
interrupt
打断 sleep, wait, join 等阻塞状态的线程
会清空打断状态
**
* 打断 sleep 等阻塞状态的线程,会清空打断状态
*/
public class InterruptDemo1 {
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(()->{
try {
System.out.println("t1 睡眠……");
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
});
t1.start();
TimeUnit.SECONDS.sleep(1);
t1.interrupt();
System.out.println("t1 被打断");
System.out.println(t1.isInterrupted());// sleep wait join 等阻塞状态的线程被打断,会清空打断状态
}
}
/**
* 打断 正常运行状态的线程,是否停止由线程自己决定;
*/
public class InterruptDemo2 {
public static void main(String[] args) throws InterruptedException {
Thread thread = new Thread(() -> {
while (true){
boolean interrupted = Thread.currentThread().isInterrupted();
if(interrupted){
break;
}
System.out.println("t1 正在执行");
}
}, "t1");
thread.start();
TimeUnit.SECONDS.sleep(1);
thread.interrupt();
System.out.println("t1 被打断了……");
}
}
模式之两阶段终止(Two Phase Termination)
如何在线程 T1 中“优雅”的终止线程T2。
错误思路
- 使用线程对象的 stop() 方法,会真正的杀死线程,如果这是线程锁住了共享资源,被杀死后,就再也没有机会释放锁了,其他线程永远无法获取锁
-
使用 System.exit(int) 方法停止线程,会让整个程序停止
image.png
/**
* 两阶段终止模式(Two Phase Termination)
* 模拟系统监控程序
*/
public class InterruptDemo3 {
public static void main(String[] args) throws InterruptedException {
TwoPhaseTermination twoPhaseTermination = new TwoPhaseTermination();
twoPhaseTermination.start();
Thread.sleep(3500);
twoPhaseTermination.stop();
}
}
class TwoPhaseTermination {
//监控线程
Thread monitor;
//启动
public void start(){
monitor = new Thread(()->{
while (true){
Thread current = Thread.currentThread();
//判断是否被打断,如果被打断,则善后、退出循环
if(current.isInterrupted()){//另外一个静态方法 interrupted 会清除打断标记
System.out.println("正在处理善后工作……");
break;
}
//如果没有被打断,则睡眠 1 秒,执行监控逻辑代码
try {
TimeUnit.SECONDS.sleep(1);// 被打断情况1
System.out.println("正在执行监控逻辑……");// 被打断情况2
} catch (InterruptedException e) {
e.printStackTrace();
current.interrupt();
}
}
});
monitor.start();
}
//停止
public void stop(){
monitor.interrupt();
}
}
打断 park 线程
/**
* interrupt 打断 park 线程
* 被打断后 interrupt:true 再 park 就失效了
*/
public class InterruptDemo4 {
public static void main(String[] args) {
test();
}
public static void test(){
Thread t = new Thread(()->{
System.out.println("线程正在执行");
System.out.println("park");
LockSupport.park();
System.out.println("unpark");
// System.out.println("打断状态:"+Thread.currentThread().isInterrupted());
System.out.println("打断状态:"+Thread.interrupted());
LockSupport.park();
System.out.println("unpark");
});
t.start();
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
t.interrupt();
}
}