zoukankan      html  css  js  c++  java
  • 玩转多线程

    目录:

    • 创建多线程的三种方式
      • extends Thread
      • implements Runnable
      • 匿名类
        • 线程创建方式
        • 有关构造函数中使用匿名类的说明
    • 多线程的核心理论
      • 共享性
      • 互斥性
      • 原子性
      • 可见性
      • 有序性
    • synchronized
      • 使用方法
      • 内核剖析
    • volatile
      • 使用方法
      • 使用场景
    • 多线程生命周期图
    • 线程安全的容器

    多线程的内容有的是笔者自己总结,有的会直接推荐优质博客。

    自己总结的部分一般包含个人实践时的经验和需要注意的坑点。

    创建多线程的三种方式

    三种方式的核心均是对Thread类中run方法进行override

    1.extends Thread
    public class CreateThreadMethod {
        public static void main(String[] args) {
            extendsMethod thread = new extendsMethod();
            thread.start();
        }
    }
    
    class extendsMethod extends Thread {
        @Override
        public void run() {
            for (int i = 9; i >= 0; i--) {
                System.out.println("extendsMethod's Thread:" + i);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                }
            }
        }
    }
    
    2.implements Runnable
    public class CreateThreadMethod {
        public static void main(String[] args) {
            Thread thread = new Thread(new implementsMethod());
            thread.start();
        }
    }
    
    class implementsMethod implements Runnable {
        @Override
        public void run() {
            for (int i = 0; i < 10; i++) {
                System.out.println("implementsMethod's Thread:" + i);
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                }
            }
        }
    }
    
    3.匿名类

    多线程创建方式:

    public class CreateThreadMethod {
        public static void main(String[] args) {
            Thread thread = new Thread(new Runnable() {
                @Override
                public void run() {
                    for (int i = 9; i >= 0; i--) {
                        System.out.println("The third method's Thread:" + 3 * i);
                        try {
                            Thread.sleep(500);
                        } catch (InterruptedException e) {
                        }
                    }
                }
            });
            thread.start();
    
        }
    }
    

    有关匿名类在构造函数中使用的说明:

    先看如下例子:

    public class ThisEscape {
      private final int num;
     
      public ThisEscape(EventSource source) {
        //在构造函数中直接使用匿名类 
        source.registerListener(
            new EventListener() {
              public void onEvent(Event e) {
                doSomething(e);
              }
            });
        num = 42;
      }
    
      private void doSomething(Event e) {
        if (num != 42) {
          System.out.println("Race condition detected at " +
              new Date());
        }
      }
    }
    

    上述class编译之后分为两部分:

    outer class:

    public class ThisEscape {
      private final int num;
    
      public ThisEscape(EventSource source) {
        source.registerListener(new ThisEscape$1(this));
        num = 42;
      }
    
      private void doSomething(Event e) {
        if (num != 42)
          System.out.println(
              "Race condition detected at " + new Date());
      }
    
      static void access$000(ThisEscape _this, Event event) {
        _this.doSomething(event);
      }
    }
    

    anonymous inner class:

    class ThisEscape$1 implements EventListener {
      final ThisEscape this$0;
    
      ThisEscape$1(ThisEscape thisescape) {
        this$0 = thisescape;
        super();
      }
    
      public void onEvent(Event e) {
        ThisEscape.access$000(this$0, e);
      }
    }
    

    试想:如果一个线程足够快,那么就有可能在num还被初始化为42之前,匿名类已经调用了doSomething()这个时候就会抛出NullPointerException

    那么一个类的构造函数要怎么写才会避免类似的错误出现呢?

    • 永远不要在构造器内创建内部类,无论是匿名类,还是staticnon-static
    • 在构造器中不要把this当成参数传递给其他的类或方法
    • 在构造器中只调用private方法

    多线程的核心理论

    详见博客:多线程的核心理论

    synchronized:

    对方法加锁 == 对对象加锁,即synchronized this

    关于synchronized的内核剖析详见博客:synchronized的内核剖析

    volatile

    个人使用经验是:对于一些标志位,常采用volatile

    关于volatile的具体解析:volatile

    多线程生命周期图

    思考:图中涉及的wait方法和sleep方法,为什么wait方法在Object类,而sleep方法在Thread类?

    两者都可以让线程暂停一段时间,但是本质的区别在于sleep方法是线程的运行状态控制,而wait方法是线程之间的通讯

    线程安全的容器:

    详见博客:线程安全的容器

  • 相关阅读:
    WPF数据绑定之Ado.net的数据库连接绑定
    asp.net 网站js弹出提示后原页面css样式丢失
    Javascript中函数重载的实现
    JavaScript的继承
    WPF数据绑定之4种绑定模式
    Asp.net输出Excel文件并且下载该文件以及某些细节问题解决
    js 验证身份证 带X
    WPF的数据绑定之控件源绑定以及代码方式绑定
    WPF数据绑定之DataContext
    在无cookie模式中,会话话状态的ID将会自动保存在ASP.NET的查询字符串中
  • 原文地址:https://www.cnblogs.com/joeye153/p/12539177.html
Copyright © 2011-2022 走看看