美文网首页
嗨~! 线程 —— 持续更新(^-^)V

嗨~! 线程 —— 持续更新(^-^)V

作者: SonyaBaby | 来源:发表于2019-05-29 16:05 被阅读0次
    进阶线程啦~.png

    进程

    是了解线程之前的首要概念,当我们想要在系统中运行程序,首先需要向操作系统申请资源(内存、文件句柄),申请资源在操作系统中的基本单位是进程。一个进程可以包含多个线程,同一个进程中的线程共享该进程中的资源,如内存空间、文件句柄等

    HelloThread

    线程创建、启动、运行
    新建线程 new
    启动线程 start
    运行线程 run -- 运行一个线程就是让JVM执行该线程的 run 方法

      public class HelloThread {
        public static void main(String[] args) {
          Thread thread = new Thread();
          Thread childThread = new ChildThread();
          Thread childThred2 = new Thread(new ChildThread());
          Thread student = new Thread(new StudentRunnable());
          System.out.println("----------- Test thread's name in Called Method -----------");
          threadName();
          
          System.out.println("----------- Test 1. new Thread() 2.setName(\"HelloWorld\") -----------");
          thread.setName("HelloWorld");
          thread.start();
          System.out.println("Thread: " + thread.getName() + " starting");
          
          System.out.println("----------- Test ChildThread -----------");
          childThread.start();
          System.out.println("ChildThread: " + childThread.getName() + " starting...");
          childThred2.start();
          // 线程是“一次性用品”
          // 多次调用同一 thread 的 start 会出现 IllegalThreadStateException
          // 因为threadStatus != 0 0为线程初始状态
          // childThred2.start();
          System.out.println("ChildThread: " + childThred2.getName() + " starting...");
          System.out.println("----------- Test Student of Runnable -----------");
          student.start();
          System.out.println("StudentThread: " + student.getName() + " starting...");
        }
        
        public static void threadName() {
          System.out.println("The thread name of main called method's currentThread is " + Thread
            .currentThread().getName());
        }
        
      }
    
      class ChildThread extends Thread {
        @Override
        public void run() {
          // 执行run的顺序是不一定的
          // run执行完毕,线程即结束
          // 结束后,所占用的资源包括内存都将被JVM回收
          System.out.println(Thread.currentThread().getName() + " running...");
        }
      }
    
      class StudentRunnable implements Runnable {
        
        @Override
        public void run() {
          System.out.println(Thread.currentThread().getName() + " running...");
        }
      }
    

    Console Output:

      ----------- Test thread's name in Called Method -----------
      The thread name of main called method's currentThread is main
      ----------- Test 1. new Thread() 2.setName("HelloWorld") -----------
      Thread: HelloWorld starting
      ----------- Test ChildThread -----------
      ChildThread: Thread-1 starting...
      ChildThread: Thread-3 starting...
      ----------- Test Student of Runnable -----------
      ----------- Test run of ChildThread -----------
      Thread-3 running...
      ----------- Test run of ChildThread -----------
      Thread-1 running...
      Thread-4 running...
      StudentThread: Thread-4 starting...
    
    • Thread的创建默认下标从0开始,如源码示 threadInitNumber for 匿名线程自增长编号。threadInitNumber 初始为0
        /* For autonumbering anonymous threads. */
        private static int threadInitNumber;
        private static synchronized int nextThreadNum() {
            return threadInitNumber++;
        }
    
        public Thread() {
            init(null, null, "Thread-" + nextThreadNum(), 0);
        }
    

    创建线程综述:

        @Override
        public void run() {
            if (target != null) {
                target.run();
            }
        }
    

    基于Thread的run实现(实现Runnable的run),创建线程有两种方式:
    1. 基于继承(Inheritance)。实现 Thread 中的 run 方法
    2. 基于组合(Composition)。new Thread(Ruannable instance) 通过 Runnable 的实例,执行实例中的 run。实用组合更好的降低耦合

    public class ThreadCreation {
      private static final String PREFIX = "prefix";
      
      public static void main(String[] args) {
        // ---------- 获取处理器个数 ----------
        final int processorNum = Runtime.getRuntime().availableProcessors();
        
        // ---------- 创建线程方式 ----------
        // ---------- 创建线程.Way1 基于继承 ----------
        ChildrenOfRunnable runnableTask = new ChildrenOfRunnable();
        IntStream.range(0, 2 * processorNum).mapToObj(index -> new Thread(runnableTask)).forEach(
          Thread::start);
    
        // ---------- 创建线程.Way2 基于组合 ----------
        Thread thread = new ChildrenOfThread();
        thread.start();
      }
        @Override
        public void run() {
          System.out.println("childrenOfThread is running.");
        }
      }
      
      static class ChildrenOfRunnable implements Runnable {
        private int index = 0;
        
        @Override
        public void run() {
      
      static class ChildrenOfThread extends Thread {
          System.out.println("childrenOfRunnable " + index++ + " is running.");
        }
      }
    }
    

    线程核心属性

    • id同一个JVM实例中不会存在重复的线程id,默认从0开始自增
    • name 主要便于开发人员查看,是可以重复的
    • daemon是否要设置为守护线程,默认同父线程daemon性质一致。守护线程一般执行一些重要性不是很高的任务,比如监听其他线程的运行情况
    • priority线程优先级,默认同父线程priority值一致,1≤n≤线程组priority≤10。优先级并一定保证线程会按照优先级的顺序执行,只是给到调度器一个提示信息。
    public final static int MIN_PRIORITY = 1;
    public final static int NORM_PRIORITY = 5;
    public final static int MAX_PRIORITY = 10;
    

    线程属性设置主要在Thread.init

        private void init(ThreadGroup g, Runnable target, String name, long stackSize, AccessControlContext acc) {
            if (name == null) {
                throw new NullPointerException("name cannot be null");
            }
    
            this.name = name.toCharArray();
    
            Thread parent = currentThread();
            SecurityManager security = System.getSecurityManager();
            if (g == null) {
                /* Determine if it's an applet or not */
    
                /* If there is a security manager, ask the security manager what to do. */
                if (security != null) {
                    g = security.getThreadGroup();
                }
    
                /* If the security doesn't have a strong opinion of the matter use the parent thread group. */
                if (g == null) {
                    g = parent.getThreadGroup();
                }
            }
    
            /* checkAccess regardless of whether or not threadgroup is explicitly passed in. */
            g.checkAccess();
    
            /* Do we have the required permissions? */
            if (security != null) {
                if (isCCLOverridden(getClass())) {
                    security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);
                }
            }
    
            g.addUnstarted();
    
            this.group = g;
            this.daemon = parent.isDaemon();
            this.priority = parent.getPriority();
            if (security == null || isCCLOverridden(parent.getClass()))
                this.contextClassLoader = parent.getContextClassLoader();
            else
                this.contextClassLoader = parent.contextClassLoader;
            this.inheritedAccessControlContext =
                    acc != null ? acc : AccessController.getContext();
            this.target = target;
            setPriority(priority);
            if (parent.inheritableThreadLocals != null)
                this.inheritableThreadLocals =
                    ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);
            /* Stash the specified stack size in case the VM cares */
            this.stackSize = stackSize;
    
            /* Set thread ID */
            tid = nextThreadID();
        }
    

    线程常用方法

    • synchronized void start() 启动线程。一个线程被start多次会抛出- IllegalThreadStateException异常
    • void run()实现线程的任务处理逻辑。一般,程序不应该直接调用该方法,由JVM调用
    • final synchronized void join()等待相应线程运行结束。T_A调用T_Bjoin()T_A将会等待T_B执行结束再执行
    • static void yield()主动放弃对当前时间片的占用,但是方法的执行并不可靠。若T_A调用yield方法:
      • 当前资源空闲,调度器会忽略这个提示,T_A继续执行
      • 当前资源忙,T_A主动放弃当前时间片,调度器收到提示切换上下文,T_A挂起
    • static void sleep() 一定会执行,挂起一定时间
    • static Thread currentThread()返回执行当前代码的线程
    • void interrupt()主动打断线程阻塞状态
    • boolean isInterrupted() 执行isInterrupted(false) 返回 if this thread has been interrupted; 即线程是否被打断过
    • static boolean interrupted() 实际上执行currentThread().isInterrupted(true); 即返回当前线程的interrupted并复位interrupted状态
    • native boolean isInterrupted(boolean ClearInterrupted)线程是否被打断,同时是否复位interrupted标识

    相关文章

      网友评论

          本文标题:嗨~! 线程 —— 持续更新(^-^)V

          本文链接:https://www.haomeiwen.com/subject/bpumoqtx.html