zoukankan      html  css  js  c++  java
  • 线程API

    线程方法API

    • start()

      启动线程,线程以异步的方式来执行;

      启动一次后,不可以再重复调用,否则会出现异常

    • run()

      启动异步线程后,线程run方法中的内容;

      如果直接调用run方法,那么run方法就相当于是一个普通方法,被他所在的那个线程调用,也就是同步执行,不会异步执行

    • state

      线程状态

    • sleep

      sleep方法,会让线程进入睡眠,此时线程的状态是time waiting;

      其他线程可以使用interrupt方法打断正在睡眠的线程,这时sleep线程会抛出InterruptedException,sleep线程继续执行;

      sleep结束的线程未必会立即得到执行;

      建议使用TimeUnit的sleep代替Thread的sleep来获得更好的可读性;

    • yield

      调用yield方法会让当前线程从running进入runnable就绪状态,然后调度其他线程;

      注意:调用了yield方法,并不会切换到别的线程,具体的线程依赖于操作系统的任务调度

    • 线程优先级setPriority

      线程优先级会提示cpu调度器优先调度该线程;

      如果在cpu比较忙时,优先级高的线程会获得更多的时间片,但cpu闲时,优先级几乎没有作用

    • isInterrupted

      判断是否被打断,不会清除打断标记

    • isAlive

      判读线程是否还存活

    • interrupt

      打断线程,如果线程正在sleep, wait, join会导致被打断的线程抛出InterruptedException,并清除打断标记;

      如果打断正在运行的线程,则会设置打断标记

      	public static void main(String[] args) {
              Thread thread = new Thread(()->{
                  try {
                      TimeUnit.SECONDS.sleep(5);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              });
              thread.start();
      
              try {
                  TimeUnit.SECONDS.sleep(1);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
      
              thread.interrupt();	// 打断sleep的线程,会清除标记;打断running的线程,打断标记为false
              System.out.println("线程状态:" + thread.getState() + " 打断标记:" + thread.isInterrupted());
          }
      

      输出结果:

      java.lang.InterruptedException
      	at java.lang.Thread.sleep(Native Method)
      	at java.util.concurrent.TimeUnit.sleep(TimeUnit.java:386)
      	at com.mylearn.thread.Test6.lambda$main$0(Test6.java:9)
      	at com.mylearn.thread.Test6$$Lambda$1/0x0000000000000000.run(Unknown Source)
      	at java.lang.Thread.run(Thread.java:823)
      线程状态:RUNNABLE 打断标记:false
      

      如果打断的线程是running的状态,打断标记会被置为true,但也仅仅是将打断标记置为了true,线程仍然会继续执行。

      public static void main(String[] args) {
          Thread thread = new Thread(()->{
              while(true){
                  if(Thread.currentThread().isInterrupted()){
                      break;
                  }
                  System.out.println(1);
              }
          });
          thread.start();
          thread.interrupt();
          System.out.println("线程状态:" + thread.getState() + " 打断标记:" + thread.isInterrupted());
      }
      
    • interrupted

      判断当前线程是否被打断,会清除打断标记

    • currentedThread

      获取当前正在执行的线程

    • join

      a线程调用b线程的join方法,a线程会等待b线程执行完后再继续执行。

      static int res = 0;
      
      public static void main(String[] args) {
          Thread thread = new Thread(() -> {
              try {
                  TimeUnit.SECONDS.sleep(1);
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
              res = 10;
          });
          thread.start();
          try {
              thread.join();
          } catch (InterruptedException e) {
              e.printStackTrace();
          }
          System.out.println(res);
      }
      

      如果有多个线程时,主线程可以调用多个线程的join方法,使得main线程等待所有线程都执行完再继续执行main线程。

      	static int r1 = 0;
          static int r2 = 0;
          public static void main(String[] args) {
              Thread thread1 = new Thread(()->{
                  r1 = 10;
                  try {
                      TimeUnit.SECONDS.sleep(1);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              });
              Thread thread2 = new Thread(()->{
                  r2 = 20;
                  try {
                      TimeUnit.SECONDS.sleep(2);
                  } catch (InterruptedException e) {
                      e.printStackTrace();
                  }
              });
      
              thread1.start();
              thread2.start();
              long start = System.currentTimeMillis();
      
              try {
                  thread1.join();
                  thread2.join();
              } catch (InterruptedException e) {
                  e.printStackTrace();
              }
              System.out.println(System.currentTimeMillis() - start);
          }
      

      join方法也可以指定时间来等待。

    两阶段终止模式

    概念

    在一个线程T1中,如何优雅的终止线程T2?

    错误思路

    1. 使用线程的stop方法

      stop方法会真正杀死进程,如果这时线程锁住了共享资源,那么当它被杀死后,再也没机会释放锁,其他线程永远无法获取锁

    2. 使用System.exit(1)

      这种做法会让整个程序都停止。

    正确思路

    	public static void main(String[] args) throws InterruptedException {
            TwoPhaseTermination twoPhaseTermination = new TwoPhaseTermination();
            twoPhaseTermination.start();
            TimeUnit.SECONDS.sleep(5);
            twoPhaseTermination.stop();
        }
    
        static class TwoPhaseTermination {
            private Thread monitorThread;
    
            public void start() {
                monitorThread = new Thread(() -> {
                    while (true) {
                        Thread current = Thread.currentThread();
                        if (current.isInterrupted()) {
                            System.out.println("料理后事");
                            break;
                        }
                        try {
                            TimeUnit.SECONDS.sleep(1);
                            System.out.println("running monitor");
                        } catch (InterruptedException e) {
                            current.interrupt();
                        }
                    }
                });
                monitorThread.start();
            }
    
            public void stop() {
                monitorThread.interrupt();
            }
        }
    

    打断park的线程

    可以使用工具类LockSupport来使线程暂停,可以使用interrupt打断正在park的线程,被打断的park线程无法再次park,除非清除打断标记。

    	public static void main(String[] args) throws InterruptedException {
            Thread t1 = new Thread(() -> {
                System.out.println("park...");
                LockSupport.park();
                System.out.println("unpark");
                LockSupport.park();
                System.out.println("打断标记: " + Thread.currentThread().isInterrupted());
                System.out.println("打断标记: " + Thread.interrupted());
                LockSupport.park();
    
            });
            t1.start();
    
            TimeUnit.SECONDS.sleep(1);
            t1.interrupt();
        }
    

    过时不推荐的方法

    • stop
    • suspend
    • resume

    主线程和守护线程

    设置守护线程: setDaemon(true)

  • 相关阅读:
    Docker--简介&&安装
    Mycat
    Mysql--主从复制
    Nginx--平滑升级
    Nginx--rewrite
    Nginx--缓存
    Mysql--SQL语句
    Nginx--虚拟主机
    Nginx--反向代理&&负载均衡
    Nginx--用户认证&&访问控制&&限速&&状态访问
  • 原文地址:https://www.cnblogs.com/lfdingye/p/15418779.html
Copyright © 2011-2022 走看看