线程状态
线程方法
方法 | 说明 |
---|---|
setPriority(int newPriority) | 更改线程的优先级 |
static void sleep(long millis) | 在指定的毫秒数内让当前正在执行的线程休眠 |
void join() | 等待该线程终止 |
static void yield() | 暂停当先正在执行的线程对象,并执行其他线程 |
void interrupt() | 中断线程,不要使用这个方法 |
bollean isAlive() | 测试线程是否处于活动状 |
停止线程
- 不推荐使用JDK提供的stop()、destroy()方法。【已弃用】
- 推荐使用自己的停止方法。
- 建议使用一个标志位进行终止变量,当flag=false,则终止线程运行
public class TestStop implements Runnable{
//1.线程中定义线程体使用的标志
private boolean flag = true;
@Override
public void run(){
//2.线程体使用该标志
while(flag){
System.out.println("run...Thread");
}
}
//3.对外提供方法改变标识
public void stop(){
this.flag = false;
}
//测试
public static void main(String[] args){
TestStop testStop = new TestStop();
new Thread(testStop).start();
for(int i = 0; i < 100; i++){
if(i == 50){
//调用stop方法切换标志位,使线程停止
testStop.stop();
System.out.println("该线程停止...")
}
}
}
}
线程休眠
- 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;
}
}
模拟倒计时
public class TestTimeDown{
public static void main(String[] args){
Date startTime = new Date(System.currentTimeMillis()); //获取系统当前时间
while(true){
try{
Thread.sleep(1000);
System.out.println(new SimpleDateFormat("HH:mm:ss").format(startTime));
startTime = new Date(System.currentTimeMillis()); //更新当前时间
}catch(InterruptedException e){
e.printStackTrace();
}
}
}
//模拟倒计时
public static void tenDown() throws InterruptedException{
int num = 10;
while(true){
Thread.sleep(1000); //单位:毫秒
System.out.println(num--);
if(num <= 0){
break;
}
}
}
}
线程礼让
- 礼让线程,让当前正在执行的线程暂停,但不阻塞
- 将线程从运行状态转为就绪状态
- 让CPU重新调度,礼让不一定成功,看CPU心情
public class TestYield{
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 礼让
- Join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞
- 可以理解为插队
public class JoinTest implements Runnable{
@Override
public void run(){
for(int i = 0; i < 100; i++){
System.out.println("VIP线程"+i+"来额");
}
}
public static void main(String[] args){
//启线程
JoinTest joinTest = new JoinTest();
Thread thread = new Thread(joinTest);
thread.start();
//主线程
for(int i = 0; i < 200; i++){
if(i == 30){
thread.join();
}
}
}
}
线程状态观测
-
Thread.State
线程状态,线程可以处于以下状态之一。
-
NEW
尚未启动的线程处于此状态
-
RUNNABLE
在Java虚拟机中执行的线程处于此状态
-
BLOCKED
被阻塞等待监视器锁定的线程处于此状态
-
WAITING
正在等待另一个线程执行特定动作的线程处于此状态
-
TIMED_WAITING
正在等待另一个线程执行动作达到指定等待时间的线程处于此状态
-
TERMINATED
已退出的线程处于此状态
-
一个线程客户以在给定时间点处于一个状态。这些状态是不反映任何操作系统线程状态的虚拟机状态。
线程优先级
-
Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行。
-
线程的优先级用数字表示,范围从1~10
- Thread.MIN_PRIORITY = 1;
- Thread.MAX_PRIORITY = 10;
- Thread.NORM_PRIORITY = 5;
-
使用以下方式改变或获取优先级
- getPriority().setPriority(int xxx)
优先级低只是意味着获得调度的概率低,并不是优先级低就不会被调用了,这就是看CPU的调度,当优先级低的先执行就会是“性能倒置”
优先级的设定建议在start()调度前(先设置优先级在start跑)
守护线程(daemon)
- 线程分为用户线程和守护线程
- 虚拟机必须确保用户线程执行完毕
- 虚拟机不用等待守护线程执行完毕
- such as,后台记录操作日志,监控内存,垃圾回收(gc)等待…
注意:守护线程不能持有任何需要关闭的资源,例如打开文件等,因为虚拟机退出时,守护线程没有任何机会来关闭文件,这会导致数据丢失。
public class DaemonTest{
public static void main(String[] args){
God god = new God();
You you = new You();
Thread thread = new Thread(god);
thread.setDaemon(true); //默认是false表示是用户线程,正常的线程都是用户线程
}
}
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("你开心的活了"+i+"天");
}
}
}