多线程知识点

2019-01-15  本文已影响0人  wuhuaguo丶

谈谈对线程的理解

简单来说,一程序可以调用多个进程,比如一个视频播放器程序,里面就存在两个进程:一个是播放视频的进程,一个是下载上传视频的进程。

一个进程又同时调用多个线程,这个线程是隐藏的,用进程管理器看不到,可用其它的进程管理软件来查看。

三者的逻辑关系是程序调用进程,进程调用线程,一般来说程序下面都是多进程,不同的进程分工不同;进程下面也基本上是多线程的。

可以这样下定义:进程是系统进行资源分配和调用的独立单位,每一个进程,都由它自己的内存空间和系统资源

线程是进程的执行单元,执行路径,线程也是程序使用CPU的最基本单位


run方法和start方法的区别

run方法相当于普通方法,并没有实现多线程程序中依然只有一个主线程。相当于调用Thread类中的run方法。
用start方法来启动线程,真正实现了多线程,无需等待run方法执行完毕。而是直接执行下面的代码。执行start()方法,可以在主线程中重新创建一个新的线程,等得到CPU的时候就回去执行对应的run方法内的代码。


ThreadLocal

ThreadLocal,顾名思义,为线程的局部变量,该变量只能让当前线程访问,独立于其他线程,可以保证并发环境下数据的安全。

  //private static final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  private static ThreadLocal<SimpleDateFormat> tl = new ThreadLocal<SimpleDateFormat>();
  public static class ParseDate implements Runnable{
      int i = 0;
      public ParseDate(int i){
          this.i = i;
      }
      @Override
      public void run() {
      //            try {
      //                Date t = sdf.parse("2018-04-10 16:00:" + i%60);
      //                System.out.println(i + ":" + t);
      //            } catch (ParseException e) {
      //                e.printStackTrace();
      //            }
          if(tl.get() == null){
              tl.set(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
          }
          try {
              Date t = tl.get().parse("2018-04-10 16:00:" + i%60);
              System.out.println(i + ":" + t);
          } catch (ParseException e) {
              e.printStackTrace();
          }
      }
  }
  public static void main(String[] args) {
      ExecutorService es = Executors.newFixedThreadPool(10);
      for(int i = 0;i < 1000;i++){
          es.execute(new ParseDate(i));
      }
      es.shutdown();
  }

主要是两个方法

  1. void set(Object value)
    设置当前线程的线程局部变量的值。
  2. public Object get()
    该方法返回当前线程所对应的线程局部变量。

通过ThreadLocal对象实例调用get()和set()方法,首先就是获得线程对象,然后拿到线程对象的ThreadLocalMap对象,最后对该Map对象进行存取。因为每个线程都有一个自己的map容器,所以做到了线程独享。
ThreadLocal使用场景
不需要共享的变量。比如Web中,每个用户的requestid不一样,使用ThreadLocal声明就可以有效的避免线程之间的竞争,无需采取同步措施,因此可以简单的理解为用空间换时间。

深入理解ThreadLocal
Java并发编程:深入剖析ThreadLocal


Java创建线程的方式?哪种比较好

有四种方式创建线程

  1. 继承Thread类
  2. 实现Runnable接口
  3. 使用线程池创建
  4. 实现Callable接口

实现Runnable接口比继承Thread类所具有的优势:

  1. 适合多个相同的程序代码的线程去处理同一个资源
  2. 可以避免Java中单继承的限制
  3. 线程池只能放入实现Runnable或Callable的线程,不能直接放入继承Thread的类
  4. runnable 实现线程可以对线程进行复用, 因为 runnable 是轻量级的对象, 重复 new 不会耗费太大资源, 而 Thread 则不然, 它是重量级对象, 而且线程执行完就完了, 无法再次利用。

说一下死锁?


多线程共用一个数据变量时需要注意什么?

  1. 如果多个线程对数据只有读没有写的话,不用进行特殊操作
  2. 如果既有读又由写,那么需要保证线程安全,防止脏读,可以使用volatile关键字保证内存可见性,如果这还不能保证线程安全的话,那么就要使用加锁来保证操作的可见性和原子性来保证线程安全。

上一篇 下一篇

猜你喜欢

热点阅读