目录
线程状态
线程方法
setPriority(int newPriority) //更改线程的优先级
static void sleep(long millis) //在指定的毫秒数内让当前正在执行的线程休眠
void join() //等待该线程终止再执行其他线程
static void yield() //暂停当前正在执行的线程对象,并执行其他线程
void interrupt() //中断线程,别用这个方式
boolean isAlive() //测试线程是否处于活动状态
停止线程
/*
* 1.建议线程正常停止-->利用次数,不建议死循环
* 2.建议使用标志位-->设置一个flag标志位
* 3.不要使用stop或者destroy等过时或者JDK不建议使用的方法
* */
public class TestStop implements Runnable {
//1、设置标志位
private boolean flag = true;
@Override
public void run() {
while (flag){//标志位为true时,线程才跑起来
System.out.println("Thread is running...");
}
}
//2、设置公开的方法通过修改标志位来停止线程
public void stopThread(){
this.flag = false;
}
public static void main(String[] args) {
TestStop stopThread = new TestStop();
new Thread(stopThread).start();
for (int i = 0; i < 1000; i++) {
System.out.println("main is " + i);
if (i == 100){
//调用stopThread()方法切换标志位,让线程停止
stopThread.stopThread();
System.out.println("Thread stopped.");
break;
}
}
}
}
线程休眠
-
sleep(时间) 指定当前线程阻塞的毫秒数
-
sleep存在异常InterruptedException
-
sleep时间达到后线程进入就绪状态
-
sleep可以模拟网络延时、倒计时等
-
每一个对象都有一个锁,sleep不会释放锁
//模拟网络延时:放大问题的发生性
public class TestSleep implements Runnable {
private int ticketNums = 10;//票数
@Override
public void run() {
while (true){
if (ticketNums <= 0){
break;
}
//模拟延时
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "-->拿到了第" + ticketNums-- + "张票");
}
}
public static void main(String[] args) {
TestSleep testSleep = new TestSleep();
//多个对象操作同一个线程容易出现线程不安全问题
new Thread(testSleep,"张三").start();
new Thread(testSleep,"李四").start();
new Thread(testSleep,"王五").start();
}
}
import java.text.SimpleDateFormat;
import java.util.Date;
//模拟倒计时
public class TestSleep2 {
public static void main(String[] args) {
//三秒钟倒计时
try {
countDown(3);
} catch (InterruptedException e) {
e.printStackTrace();
}
//打印当前系统时间
Date startTime = new Date();//获取系统当前时间
while (true){
try {
//System.out.println(new SimpleDateFormat("HH:mm:ss").format(System.currentTimeMillis()));
System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
Thread.sleep(1000);
startTime = new Date();//更新系统当前时间
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//模拟倒计时
public static void countDown(int seconds) throws InterruptedException {
while (true){
if (seconds <= 0){
break;
}
Thread.sleep(1000);
System.out.println(seconds--);
}
}
}
线程礼让
-
礼让线程,让当前正在执行的线程暂停,但不阻塞
-
将线程从运行状态转为就绪状态
-
让CPU重新调度,礼让不一定成功!看CPU心情
public class TestYield {
public static void main(String[] args) {
MyYiled myYiled = new MyYiled();
new Thread(myYiled,"A").start();
new Thread(myYiled,"B").start();
}
}
class MyYiled implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "线程开始执行");
Thread.yield();//线程礼让,不一定礼让成功
System.out.println(Thread.currentThread().getName() + "线程执行结束");
}
}
Join线程合并
-
待此线程执行完成后,再执行其他线程,此时其他线程阻塞
-
可以想象成插队
public class TestJoin implements Runnable{
@Override
public void run() {
for (int i = 0; i < 200; i++) {
System.out.println("vip线程来了" + i);
}
}
public static void main(String[] args) throws InterruptedException {
TestJoin testJoin = new TestJoin();
Thread thread = new Thread(testJoin);
thread.start();//启动线程
//主线程
for (int i = 0; i < 50; i++) {
if (i == 25){
thread.join();//让vip线程插队,此时必须所有vip线程执行结束后,才继续执行主线程
}
System.out.println("主线程" + i);
}
}
观测线程状态
-
NEW 尚未启动的线程
-
RUNNABLE 在Java虚拟机中执行的线程
-
BLOCKED 被阻塞等待监视器锁定的线程
-
WAITING 正在等待另一个线程执行特定动作的线程
-
TIMED_WAITING 正在等待另一个线程执行动作达到指定等待时间的线程
-
TERMINATED 已经退出的线程
//观察测试线程状态
public class TestState {
public static void main(String[] args) {
Thread thread =new Thread(() -> {
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(600);
} 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 (state != Thread.State.TERMINATED){//只要线程不终止,就一直输出线程当前状态
try {
Thread.sleep(100);
state = thread.getState();//更新线程状态
System.out.println(state);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
//thread.start(); 处于TERMINATED状态的线程无法再次被启动,否则报IllegalThreadStateException错
}
}
线程优先级
-
线程调度器监控所有进入就绪状态的线程,调度器根据优先级决定线程执行先后顺序
-
优先级范围1~10
-
Thread.MIN_PRIORITY = 1; //最小优先级
-
Thread.MAX_PRIORITY = 10; //最大优先级
-
Thread.NORM_PRIORITY = 5; //默认优先级
-
-
获取优先级:getPriority()
-
设置优先级:setPriority(int xxx)
-
注意:
-
优先级的设置在start()调度前
-
优先级低只是意味着获得调度的概率低,并不是优先级低就不会被调用
-
守护线程
-
线程分为用户线程和守护线程
-
虚拟机必须确保用户线程执行完毕
-
虚拟机不用等待守护线程执行完毕
-
守护线程有:后台记录操作日志、监控内存、垃圾回收等
public class TestDaemon {
public static void main(String[] args) {
God god = new God();
Thread thread = new Thread(god);
thread.setDaemon(true);//设置为守护线程
thread.start();
new Thread(new You()).start();
}
}
class God implements Runnable{
@Override
public void run() {
while (true){
System.out.println("上帝守护着你!");
}
}
}
class You implements Runnable{
@Override
public void run() {
for (int i = 0; i < 36500; i++) {
System.out.println("开开心心每一天!");
}
System.out.println("goodbye world!");
}
}