多线程复习学习
前文链接:多线程学习小计
1.线程状态
- 新生状态(New)
- 线程对象一旦创建就进入到了新生状态;
- 就绪状态(Waitting)
- 当调用start()方法,线程立即进入就绪状态,但不意味着立即调度,需要等cpu调度;
- 阻塞状态(Blocked)
- 当调用sleep,wait或同步锁定时,线程进入阻塞状态,就是代码不往下执行,阻塞时间解除后,重新进入就绪状态,等待cpu调度;
- 运行状态(Runnable)
- 进入运行状态,线程才真正执行线程体的代码块;
- 死亡状态(Terminated)
- 线程终端或者结束,一旦进入死亡状态,就不能再次启动;
2 .停止线程(Stop)
- 建议线程正常停止,利用次数,不建议死循环
- 建议使用标志位,设置一个标志位停止
- 不要使用原生的stop或destory等过时或者JDK不建议使用的方法
- 案例练习如下:
package com;
//测试stop
public class demo08 implements Runnable{
//1.设置一个标志位
private boolean flag = true;
@Override
public void run() {
int i = 0;
while (flag){
System.out.println("run....Thread"+i++);
}
}
//2.设置一个公开的方法停止线程,转换标志位
public void stopThread(){
this.flag = false;
}
public static void main(String[] args) {
demo08 thread = new demo08();
new Thread(thread).start();
for (int i = 0; i < 1000; i++) {
System.out.println("main...."+i);
if (i==900){
//调用定义好的stopThread方法转换标志位,让线程停止
thread.stopThread();
System.out.println("线程Thread停止了");
}
}
}
}
3. 线程休眠(Sleep)
- sleep(时间)指定当前当前线程阻塞的毫秒数;
- sleep存在异常InterruptedException;
- sleep时间达到后线程进入就绪状态;
- sleep可以模拟网络延时、倒计时等;
- 每一个对象都有一个锁,sleep不会释放锁;
4.线程礼让(Yield)
- 礼让线程,让当前正在执行的线程暂停,但不阻塞;
- 将线程从运行状态装为就绪状态;
- 让cpu重新调度,礼让不一定成功!看cpu心情,可能礼让的线程会被重新调度进去;
- 案例如下:
package com;
//测试礼让线程
//礼让不一定成功
public class Demo09 {
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()+"线程停止执行");
}
}
5.线程插入(Join)
- Join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞;
- 可以想象成插队;
- 案例如下:
package com;
//测试join方法
public class Demo10 implements Runnable{
@Override
public void run() {
try {
//插队前和主线程是同步进行的,sleep一秒防止插队前已经跑完了。。。
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
for (int i = 0; i < 100; i++) {
System.out.println("vip来了"+i);
}
}
public static void main(String[] args) throws InterruptedException {
Demo10 demo10 = new Demo10();
Thread thread = new Thread(demo10);
thread.start();
for (int i = 0; i < 1000; i++) {
if (i==200){
thread.join();
}
System.out.println("main"+i);
}
}
}
6. 其他
1.观察线程的状态
thread.getState();
2.线程的优先级
- Java提供一个线程调度器来监控程序中启动后计入就绪状态的所有线程,线程调度器调度时,优先级高的,则权重高,被调度到的机会就会大,比如一百张彩票有一张有奖,给你99张也不一定中奖;
- 线程的优先级用数字表示,范围从1~10;
Thread.MIN_PRIORITY = 1;
Thread.MAX_PRIORITY = 10;
Thread.NORM_PRIORITY = 5;
getPriority().setPriority(int xxx);
- 案例如下:
package com;
public class Demo11{
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
MyPriority myPriority = new MyPriority();
Thread t1 = new Thread(myPriority);
Thread t2 = new Thread(myPriority);
Thread t3 = new Thread(myPriority);
Thread t4 = new Thread(myPriority);
t1.setPriority(Thread.MIN_PRIORITY);//最小1
t1.start();
t2.setPriority(2);
t2.start();
t3.setPriority(8);
t3.start();
t4.setPriority(Thread.MAX_PRIORITY);//最大10
t4.start();
}
}
class MyPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
}
}
- 结果很明显,优先级高不代表能先执行,只能代表权重高,被cpu调用的几率高;
3.守护(daemon)线程
- 线程分为用户线程和守护线程;
- 虚拟机必须确保用户线程(如main线程)执行完毕;
- 虚拟机不用等待守护线程(如gc垃圾回收线程)执行完毕,如后台记录仪操作日志,监控内存,垃圾回收等;
- 案例如下:
package com;
//测试守护线程
public class Demo12 {
public static void main(String[] args) {
God god = new God();
People people = new People();
Thread thread = new Thread(god);
thread.setDaemon(true);//默认为false,即默认为用户线程
thread.start();
new Thread(people).start();
}
}
//守护线程
class God implements Runnable{
@Override
public void run() {
while (true){
System.out.println("守护线程运行中。。。。");
}
}
}
//用户线程
class People implements Runnable{
@Override
public void run() {
for (int i = 0; i < 100; i++) {
System.out.println("用户线程运行中");
}
System.out.println("用户线程结束了==============");
}
}
- 输出结果可见,用户线程结束后,jvm不会管守护线程并关闭jvm,但在关闭前守护线程还是会继续运行的