线程

作者: MHLEVEL | 来源:发表于2020-07-28 12:40 被阅读0次

    Thread 属于 java.lang包,所以可以直接用,不需要引入

    • Thread 类的 sleep() 方法是一个静态方法
    public static void printSlowly(String text, long interval) throws InterruptedException {
            for (char ch : text.toCharArray()) {
                Thread.sleep(interval);
                System.out.print(ch + " ");
            }
            System.out.println();
        }
    
    • 线程栈


      线程栈
    • 代码是被线程执行的,任何代码都可以通过Thread.currentThread() 获取执行当前代码的线程

    System.out.println("程序开始,执行的线程名字叫做" + Thread.currentThread().getName());
    

    创建线程的方式

    • 方式一 : 继承并实现 Runable 接口中的run()方法
    
    public static void main(String[] args){
            Thread thread = new Thread(new PrintStoryRunnable("pilibala", 300));
    }
    static class PrintStoryRunnable implements Runnable {
            private String text;
            private long interval;
    
            public PrintStoryRunnable(String text, long interval) {
                this.text = text;
                this.interval = interval;
            }
    
            @Override
            public void run() {
                try {
                    double num = Math.random();
                    System.out.println("执行这段代码的线程名字叫做" + Thread.currentThread().getName());
                    printSlowly(text, interval);
                    System.out.println(Thread.currentThread().getName() + "执行结束");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    

    同步控制之synchronized

    • synchronized 关键字用来修饰成员方法,代表这个方法对于同一个对象来说,同一时间只允许一个线程执行,别的线程如果也调用这个实例方法,就需要等待已经在执行这个方法的线程执行完毕,才能进入方法执行。
    public synchronized void change(){
            //balabala
    }
    
    • synchronized 代码块
      就是我用 synchronized 修饰的代码块里的代码是一次只能有一个线程调用的,代码块之外的不受影响
    // 只要不是 null ,任何一个对象都可以用来做锁
    private Object lockObj = new Object();
    synchronized (lockObj){
                number += delta;
    }
    
    • synchronized 修饰静态方法 (效果等同于用synchronized 所有当前类)
    public synchronized static void changedata(){
            // method body
    }
    
    // synchronized 修饰静态方法的效果等同于用 synchronized 锁住当前类
    // 例如当前类的类名是 DataHolder
    
    synchronized (DataHolder.class){
            // balabala
    }
    

    守护线程

    • 守护线程是个好东西,比如有些程序中需要有一些辅助线程去执行一些任务,比如说程序需要做一些垃圾回收,反正就是做一些辅助任务。我们知道,Java程序入口就是启动main线程,main线程又去启动其他线程,当所有线程都运行结束时,JVM退出,进程结束,但是!这时还有一些原来作为辅助线程的线程还没退出怎么办??我JVM都退出不了🙄️~,这时我们就可以把这些作为辅助线程的线程设置为守护线程,只要程序中非守护线程执行结束,守护线程不管是不是在执行,JVM都可以退出。(守护线程工具人👹实锤
    // 设置守护线程的方法就是在线程调用start() 方法前调用 setDeamon(true)
    

    wait 和 notify 用于多线程协调运行

    • synchronized 内部可以调用wait()使线程进入等待状态。
    • 必须在已获得锁对象上调用wait() 方法。
    • 在synchronized 内部可以调用 notify() or notifyAll() 唤醒其他等待线程。
    • 必须在已获得锁对象上调用notify() or notifyAll() 方法。
    • 已唤醒的线程还需要重新获得锁后才能继续执行。
    • wait() 方法要以 try/catch 包覆,或是掷出 InterruptedException 才行,否则编译时会报错。
      使用notify() & wait()
      练习题

    join : Waits for this thread to die.

    /**
         * Waits for this thread to die.
         *
         * <p> An invocation of this method behaves in exactly the same
         * way as the invocation
         *
         * <blockquote>
         * {@linkplain #join(long) join}{@code (0)}
         * </blockquote>
         *
         * @throws  InterruptedException
         *          if any thread has interrupted the current thread. The
         *          <i>interrupted status</i> of the current thread is
         *          cleared when this exception is thrown.
         */
        public final void join() throws InterruptedException {
            join(0);
        }
    
    public final synchronized void join(long millis)
        throws InterruptedException {
            long base = System.currentTimeMillis();
            long now = 0;
    
            if (millis < 0) {
                throw new IllegalArgumentException("timeout value is negative");
            }
    
            if (millis == 0) {
                while (isAlive()) {
                    wait(0);
                }
            } else {
                while (isAlive()) {
                    long delay = millis - now;
                    if (delay <= 0) {
                        break;
                    }
                    wait(delay);
                    now = System.currentTimeMillis() - base;
                }
            }
        }
    

    java.lang.Thread.join(long millis, int nanos)方法实例

    ThreadLocal 是个什么东西?

    • 首先我们要明白很重要的一个概念在一个线程中,横跨若干方法调用,需要传递的对象,我们通常称之为上下文(Context)
    • ThreadLocal 表示线程的局部变量。
    • 使用ThreadLocal 要用try ... finally 结构,并在finally 中清除。

    volatile

    • 用 valatile 修饰的成员变量可以不被指令重排影响
    • volatile 关键字修饰的变量在运行时会强制从主存中去取数据而不是cpu的内存

    相关文章

      网友评论

          本文标题:线程

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