码迷,mamicode.com
首页 > 编程语言 > 详细

多线程状态

时间:2019-11-10 14:00:26      阅读:82      评论:0      收藏:0      [点我收藏+]

标签:image   ticket   i++   另一个   extends   size   exception   info   ali   

技术图片

方法 说明
setPriority(int newPriority) 更改线程的优先级
static void sleep(long millis) 在指定的毫秒数内让当前正在执行的线程休眠
void join() 等待该线程终止
static void yield() 暂停当前正在执行的线程对象,并执行其他线程
void interrupt() 中断线程,别用这个方式
boolean isAlive() 测试线程是否处于活动状态

停止线程:

  • 不推荐使用JDK提供的stop()、destroy()方法。【已弃用】
  • 推荐线程自己停止下来
  • 建议使用一个标志位进行终止变量,当flag=false时,则终止线程运行。

线程停止 实例代码:

 1 package com.huolongluo.coindemo.morethread.sub2;
 2 
 3 /**
 4  * Created by 火龙裸 on 2019/11/9.
 5  * desc   : 测试stop
 6  * 1.建议线程正常停止--->利用次数,不建议死循环
 7  * 2.建议使用标志位--->设置一个标志位
 8  * 3.不要使用stop或者destroy等过时或者JDK不建议使用的方法
 9  * version: 1.0
10  */
11 public class TestStop implements Runnable {
12 
13     //1.设置一个标志位
14     private boolean flag = true;
15 
16     @Override
17     public void run() {
18         int i = 0;
19         while (flag) {
20             System.out.println("run.....Thread" + (i++));
21         }
22     }
23 
24     //2.设置一个公开的方法停止线程,转换标志位
25     public void stopThread() {
26         this.flag = false;
27     }
28 
29     public static void main(String[] args) {
30         TestStop testStop = new TestStop();
31         new Thread(testStop).start();
32 
33         for (int i = 0; i < 1000; i++) {
34             System.out.println("main " + i);
35             if (i == 900) {
36                 //调用stopThread方法改变标志位状态,让线程停止
37                 testStop.stopThread();
38                 System.out.println("线程该停止了");
39             }
40         }
41     }
42 }

这段实现,当主线程的i走到900的时候,也就是当打印到“main 900”之后,会打印“线程该停止了”,这个时候,子线程就不会再打印出来“run.....Thread”了。

 

线程休眠:

  • sleep(时间)指定当前线程阻塞的毫秒数;
  • sleep存在异常InterruptedException;
  • sleep时间达到后线程进入就绪状态;
  • sleep可以模拟网络延时,倒计时等;
  • 每个对象都有一个锁,sleep不会释放锁;

线程休眠 实例代码:

 1 package com.huolongluo.coindemo.morethread.sub2;
 2 
 3 /**
 4  * Created by 火龙裸 on 2019/11/9.
 5  * desc   : 模拟网络延时:方法问题的发生性(多个线程同时操作同一个资源对象时,是线程不安全的)
 6  * version: 1.0
 7  */
 8 public class TestSleep implements Runnable {
 9     //票数
10     private int ticketNums = 10;
11 
12     @Override
13     public void run() {
14         while (true) {
15             if (ticketNums <= 0) {
16                 break;
17             }
18             //模拟延时
19             try {
20                 Thread.sleep(100);
21             } catch (InterruptedException e) {
22                 e.printStackTrace();
23             }
24             System.out.println(Thread.currentThread().getName() + " 拿到了第:" + ticketNums-- + " 张票");
25         }
26     }
27 
28     public static void main(String[] args) {
29 
30         TestSleep testSleep = new TestSleep();
31 
32         new Thread(testSleep, "小明").start();
33         new Thread(testSleep, "老师").start();
34         new Thread(testSleep, "黄牛党").start();
35     }
36 }

运行结果:

技术图片

出现-1张票,所以多个线程同时操作同一个资源对象,是不安全的。

 

线程礼让:

  • 礼让线程,让当前正在执行的线程暂停,但不阻塞
  • 将线程从运行状态转为就绪状态
  • 让CPU重新调度,礼让不一定成功!看CPU心情

线程礼让 实例代码:

 1 package com.huolongluo.coindemo.morethread.sub2;
 2 
 3 /**
 4  * Created by 火龙裸 on 2019/11/9.
 5  * desc   : 测试礼让线程
 6  * <p>
 7  * 礼让不一定成功,看CPU心情
 8  * version: 1.0
 9  */
10 public class TestYield {
11     public static void main(String[] args) {
12         MyYield myYield = new MyYield();
13         new Thread(myYield, "a").start();
14         new Thread(myYield, "b").start();
15     }
16 }
17 
18 class MyYield implements Runnable {
19     @Override
20     public void run() {
21         System.out.println(Thread.currentThread().getName() + "线程开始执行");
22         Thread.yield();//礼让
23         System.out.println(Thread.currentThread().getName() + "线程停止执行");
24     }
25 }

运行结果:

技术图片技术图片

所以礼让,有可能成功,有可能不成功。

 

合并线程:

  • Join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞。
  • 可以想象成插队。
  • 会让线程阻塞,尽量少用

线程合并 实例代码:

 1 package com.huolongluo.coindemo.morethread.sub2;
 2 
 3 /**
 4  * Created by 火龙裸 on 2019/11/9.
 5  * desc   : 测试Join方法,想象成插队,非常霸道
 6  * version: 1.0
 7  */
 8 public class TestJoin implements Runnable {
 9     @Override
10     public void run() {
11         for (int i = 0; i < 100; i++) {
12             System.out.println("线程Vip来了" + i);
13         }
14     }
15 
16     public static void main(String[] args) throws InterruptedException {
17         //启动我们的线程
18         TestJoin testJoin = new TestJoin();
19         Thread thread = new Thread(testJoin);
20         thread.start();
21 
22         //主线程
23         for (int i = 0; i < 1000; i++) {
24             if (i == 200) {
25                 thread.join();//插队(这里一插队,就是当主线程执行到i==200的时候,就让子线程去执行打印“线程Vip来了”,必须等插队的那个子线程打印100条“线程Vip”执行完了,再继续执行主线程没有执行完的语句。)
26             }
27             System.out.println("main" + i);
28         }
29     }
30 }

 

线程状态观测:

  • Thread.State

  线程状态。线程可以处于以下状态之一:

  • NEW  尚未启动的线程处于此状态
  • RUNNABLE  在Java虚拟机中执行的线程处于此状态
  • BLOCKED  被阻塞等待监视器锁定的线程处于此状态
  • WAITING  正在等待另一个线程执行特定动作的线程处于此状态
  • TIMED_WAITING  正在等待另一个线程执行动作达到指定等待时间的线程处于此状态
  • TERMINATED  已退出的线程处于此状态

一个线程可以在给定的时间点处于一个状态。这些状态是不反应任何操作系统线程状态的虚拟机状态。

线程状态观测 实例代码:

 1 package com.huolongluo.coindemo.morethread.sub2;
 2 
 3 /**
 4  * Created by 火龙裸 on 2019/11/9.
 5  * desc   : 观察测试线程的状态
 6  * version: 1.0
 7  */
 8 public class TestState {
 9     public static void main(String[] args) throws InterruptedException {
10         Thread thread = new Thread(new Runnable() {
11             @Override
12             public void run() {
13                 for (int i = 0; i < 5; i++) {
14                     try {
15                         Thread.sleep(100);
16                     } catch (InterruptedException e) {
17                         e.printStackTrace();
18                     }
19                 }
20                 System.out.println("///////");
21             }
22         });
23 
24         //观察状态
25         Thread.State state = thread.getState();
26         System.out.println(state);//NEW
27 
28         //观察启动后
29         thread.start();
30         state = thread.getState();
31         System.out.println(state);//Run
32 
33         while (state != Thread.State.TERMINATED) {//只要线程不终止,就一直输出
34             Thread.sleep(100);
35             state = thread.getState();//更新线程状态
36             System.out.println(state);//输出状态
37         }
38     }
39 }

运行结果:

技术图片

需要注意的是,死亡之后的线程是不能再次启动,否则会报错。

 

线程优先级:

  • Java提供一个线程调度器来监控程序中启动后进入就绪状态的所有线程,线程调度器按照优先级决定应该调度哪个线程来执行。
  • 线程的优先级用数字表示,范围从1~10.

    Thread.MIN_PRIORITY=1;

    Thread.MAX_PRIORITY=10;

    Thread.NORM_PRIORITY=5;

  • 使用一下方式改变或获取优先级

    getPriority(); setPriority(int xxx)

线程优先级 实例代码:

 1 package com.huolongluo.coindemo.morethread.sub2;
 2 
 3 /**
 4  * Created by 火龙裸 on 2019/11/9.
 5  * desc   : 测试线程的优先级
 6  * version: 1.0
 7  */
 8 public class TestPriority extends Thread {
 9     public static void main(String[] args) {
10         //主线程 默认优先级 为5
11         System.out.println(Thread.currentThread().getName() + "--->" + Thread.currentThread().getPriority());
12 
13         MyPriority myPriority = new MyPriority();
14 
15         Thread thread1 = new Thread(myPriority);
16         Thread thread2 = new Thread(myPriority);
17         Thread thread3 = new Thread(myPriority);
18 
19         //先设置优先级,再启动,不设置优先级,默认为5
20         thread1.start();
21 
22         thread2.setPriority(3);
23         thread2.start();
24 
25         thread3.setPriority(Thread.MAX_PRIORITY);//MAX_PRIORITY = 10
26         thread3.start();
27     }
28 }
29 
30 class MyPriority implements Runnable {
31 
32     @Override
33     public void run() {
34         System.out.println(Thread.currentThread().getName() + "--->" + Thread.currentThread().getPriority());
35     }
36 }

运行结果:

技术图片技术图片

可以看到,设置优先级,但却不一定说优先级高的就一定能先执行。因为优先级低的线程,只是说它被CPU调度的概率低,并不是说优先级低就不会被调度到,这个决定权还是得看CPU。

 

守护线程(daemon):

  • 线程分为用户线程守护线程
  • 虚拟机必须确保用户线程执行完毕
  • 虚拟机不用等待守护线程执行完毕
  • 如:后台记录操作日志,监控内存,垃圾回收等待..

可以通过setDaemon(true)把线程设置成守护线程, 默认是false,表示用户线程,正常的线程都是用户线程。

守护线程 实例代码:

 1 package com.huolongluo.coindemo.morethread.sub2;
 2 
 3 /**
 4  * Created by 火龙裸 on 2019/11/9.
 5  * desc   : 测试守护线程
 6  * <p>
 7  * 上帝守护你
 8  * version: 1.0
 9  */
10 public class TestDaemon {
11     public static void main(String[] args) {
12         God god = new God();
13         You you = new You();
14 
15         Thread thread = new Thread(god);
16         thread.setDaemon(true);//默认是false,表示用户线程,正常的线程都是用户线程
17         thread.start();//上帝 守护线程启动...
18 
19         new Thread(you).start();//你 用户线程启动...
20     }
21 }
22 
23 //上帝
24 class God implements Runnable {
25 
26     @Override
27     public void run() {
28         while (true) {//因为虚拟机不用等待守护线程执行完毕,所以这里直接给了一个true条件
29             System.out.println("上帝保佑着你");
30         }
31     }
32 }
33 
34 //
35 class You implements Runnable {
36 
37     @Override
38     public void run() {
39         for (int i = 0; i < 36500; i++) {
40             System.out.println("你一生都开心地或者");
41         }
42         System.out.println("=======goodbye! world!======");//hello ,world
43     }
44 }

程序只要当用户线程执行完毕后,就会停止,程序不会根据守护线程是否执行完毕,而是根据用户线程,用户线程执行完了,程序也就结束了。

多线程状态

标签:image   ticket   i++   另一个   extends   size   exception   info   ali   

原文地址:https://www.cnblogs.com/huolongluo/p/11826953.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!