第七天学习多线程的各种方法

多线程的各种方法

线程状态

  • 新生状态:创建(new)一个线程。
  • 就绪状态:调用start()时,线程就等待cpu调度。
  • 运行状态:cpu开始调度,进入运行状态,线程执行线程体代码块。
  • 阻塞状态:当调用sleep、wait、同步锁时,线程进入阻塞状态,代码不会继续执行,等待阻塞结束后,重新进入就绪状态,等待cpu调度。
  • 死亡状态:线程中断或结束即进入死亡状态,线程再不能。

线程方法

setPriority(int newPriority)      //更改线程优先级
static void sleep(long millis)    //指定毫秒内让当前线程休眠
void join()                       //等待线程终止
static void yield()               //暂停当前线程,执行其它线程
void interrupt()                  //中断线程
boolean isAlive()                 //测试线程是否处于活动状态    

停止线程

  • 建议线程正常停止(利用次数,不建议死循环)

  • 建议使用标志位

  • 不要使用stop或destroy等过时或JDK不建议使用的方法。

package thread;
public class ThreadTest implements Runnable {
    //1.设置一个标志位
    private boolean flag = true;

    //线程体
    @Override
    public void run() {
        int i = 0;
        while (flag){//当flag==false时线程停止
            System.out.println("线程在运行"+i++);
        }
    }

    //2.设置一个公开方法,转换标志位
    public void stop(){
        this.flag = false;
    }
    
    public static void main(String[] args) {
        ThreadTest threadTest = new ThreadTest();
        new Thread(threadTest).start();

        for (int i = 0; i < 1000; i++) {
            System.out.println("main"+i);
            if (i==900){
                threadTest.stop();
                System.out.println("线程停止了");
            }
        }
    }
}

休眠线程_sleep

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

线程休眠作用

  1. 模拟网络延时,放大问题发生性(代码见多线程创建博客)。
  2. 模拟倒计时
package thread;
//倒计时
public class TestSleep {

    public static void tenDown() throws InterruptedException {
        int num=10;
        while (true){
            Thread.sleep(1000);
            System.out.println(num--);
            if (num<=0){
                break;
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        tenDown();
    }
}

线程礼让_yield

  • 礼让线程,让当前正在执行的线程暂停,但不阻塞。
  • 将线程从运行状态转换为就绪状态。
  • 让cpu重新调度,礼让不一定成功,看cpu心情(线程A在运行,B在就绪,A执行了yield方法,A、B同时就绪,但第二次cpu又调度了A)。

线程强制执行_join

  • join合并线程,此线程执行后,其它线程才执行。
package thread;

//测试join
public class TestJoin implements Runnable {
    @Override
    public void run() {
        for (int i = 0; i < 100; 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 < 1000; i++) {
            if (i==50){
                thread.join();
            }
            System.out.println("main"+i);
        }
    }
}
  • 一开始run线程和main主线程一起跑,当主线程 i==50 时,开始全部跑run线程。

观察线程状态

package thread;

//观察测试线程状态
public class TestState {
   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);
       //观察启动后
       thread.start();
        state = thread.getState();
       System.out.println("观察线程运行时的状态---------------》"+state);//run
       //TERMINATED线程终止
       while (state!=Thread.State.TERMINATED){
           Thread.sleep(100);
           state = thread.getState();//更新线程状态
           System.out.println("观察线程休眠时(阻塞)和结束的状态---------------》"+state);
       }
       thread.start();//这里会爆出异常,线程死亡后就在其不能了!
   }
}
  • 使用thread.getState()方法即可观察到线程状态。

线程的优先级

  • 线程优先级越高,越容易被cpu调度。默认为5,可设置1-10。
package thread;
//测试线程优先级
public class TestPriorty extends Thread{

    public static void main(String[] args) {
        //主线程默认优先级
        System.out.println(Thread.currentThread().getName()+"--->"+Thread.currentThread().getPriority());

        MyPriority testPriorty = new MyPriority();
        Thread thread1 = new Thread(testPriorty,"1");
        Thread thread2 = new Thread(testPriorty,"2");
        Thread thread3 = new Thread(testPriorty,"3");
        Thread thread4 = new Thread(testPriorty,"4");
        
        //默认优先级为5
        thread1.start();

        thread2.setPriority(1);
        thread2.start();

        thread3.setPriority(4);
        thread3.start();

        thread4.setPriority(10);
        thread4.start();
    }
}

class MyPriority implements Runnable{
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"--->"+Thread.currentThread().getPriority());
    }
}

守护线程_daemon

  • 线程分为用户线程和守护线程。
  • 虚拟机必须确保用户线程执行完毕(main())。
  • 虚拟机不用等待守护线程执行完毕(gc())。
package thread;

//测试守护线程
//上帝守护你
public class TestDaemon {

    public static void main(String[] args) {
        God god = new God();
        You you = new You();

        Thread thread = new Thread(god);
        thread.setDaemon(true);//默认是false表示用户线程,正常的线程都是用户线程

        //上帝 守护线程启动
        thread.start();
        //你 用户线程启动
        new Thread(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 < 365000; i++) {
            System.out.println("开心的活了一生");
        }
        System.out.println("=============================Goodbye world");
    }
}
  • 当用户线程执行结束后,守护线程还在执行。
posted @ 2020-05-15 14:02  yukinon  阅读(165)  评论(0编辑  收藏  举报