【并发编程 | 第一篇】线程相关基础知识

打印 上一主题 下一主题

主题 1796|帖子 1796|积分 5388

1.并发和并行有什么区别

并发是指多核CPU上的多任务处置惩罚,多个任务在同一时间真正同时实行。
并行是指单核CPU上的多任务处置惩罚,多个任务在同一时间段内交替实行,通过时间片轮转实现交替实行,用于解决IO麋集型瓶颈。

如何理解线程安全呢?
如果一段代码块大概一个方法被多个线程同时并发实行,此中的共享内容还可以或许有序正确的实行,就阐明是线程安全的。
线程安全满足三个要素:
原子性:一个操作如果实行要么乐成,要么失败,不会只实行一部门。
可以通过同步关键字 synchronized 或原⼦操作,如 AtomicInteger 来包管原子性。
可见性:当一个线程修改共享变量后,其他变量可以实时看到。
可以通过 volatile 关键字来包管可⻅性。
有序性:确保线程不会由于死锁、饥饿、活锁等问题导致无法继续实行。
2.线程和历程的区别

历程:历程简单点说就是我们的电脑上启动的一个个应用,它是操作体系分配资源的最小单位。
线程:线程是历程中的独立实行单位。多个线程可以共享一个历程的资源,如内存,每个线程都有自己独立的栈和寄存器。
线程间是如何举行通讯的?

原则上可以通过消息传递和共享内存两种⽅法来实现。
Java 采用的是共享内存的并发模型。 这个模型被称为 Java 内存模型,简写为 JMM,它决定了⼀个线程对共享变量的写入,何时对别的⼀个线程可见。 当然了,本地内存是 JMM 的⼀个抽象概念,并不真实存在。
用一句话来概括就是:共享变量存储在主内存中,每个线程的私有本地内存,存储的是这个共享变量的副本。

线程A和线程B之间要通讯,有两个步调:
1、线程A把本地内存A中的共享变量副本刷新到主内存中。
2、线程 B 到主内存中读取线程 A 刷新过的共享变量,再同步到⾃⼰的共享变量副本中。

3.线程有几种创建方式?

有三种,继承Thread类、实现Runnable接口、实现Callable接口。
第一种必要重写父类的run()方法,并调用start()方法启动线程。
   class ThreadTask extends Thread {
          public void run() {
                  System.out.println("我是继承Thread类创建多线程");
        }
          public static void main(String[] args) {
                  ThreadTask task = new ThreadTask();
                  task.start();
          }
  }
  这种继承Thread类创建线程的方法缺点是,如果该类已经继承其他类,就不能继承Thread类了,由于Java是不支持多重继承的。
第二种实现Runnable接口并重写run()方法, 并且将实现类的对象作为参数传递给Thread类的构造方法,末了调用start()方法开启线程。
   class RunnableTask implements Runnable {
  public void run() {
          System.out.println("我是通过实现Runnable接口创建多线程");
  }
  public static void main(String[] args) {
                  RunnableTask task = new RunnableTask();
                  Thread thread = new Thread(task);
                   thread.start();
          }
  }
  这种方法的优点是避免了Java的单继承的限定,且更加符合面向对象的编程思想,由于Runnable接口将任务代码和线程控制的代码解耦了。
第三种实现Callable接口并重写call()方法,创建FutureTask对象,参数为实现Callable接口的示例对象,然后创建Thread对象,参数为FutureTask对象,末了调用start()方法启动线程。
   class CallableTask implements Callable {
  public String call() {
          return "我是通过实现Callable接口来创建多线程";
   }
  public static void main(String[] args) throws ExecutionException, InterruptedException {
          CallableTask task = new CallableTask();
          FutureTask futureTask = new FutureTask<>(task);
          Thread thread = new Thread(futureTask);
          thread.start();
          System.out.println(futureTask.get());
          }
  }  
  这种⽅法的优点是可以获取线程的执⾏结果。
启动一个Java步伐,你能说说里面有哪些线程吗? 

首先是main线程,这是步伐实行的入口
垃圾接纳线程,它是一个后台线程,负责接纳不再利用的对象
编译器线程,如JIT,负责把一部门热门代码编译后放到codeCache
调用start()方法可以实行run()方法,为什么不直接调用run()方法?

当调用start()方法时,会创建一个新的线程,并异步实行run()方法。
如果直接调用run()方法,就是一个普通方法的调用,不会创建新的线程,会在当火线程下直接实行,也就无法达到多线程的目的了。
也就是说,调用start() ⽅法会通知 JVM,去调⽤底层的线程调度机制来启动新线程。
调用start()方法后,线程处于就绪状态,等待底层操作体系调度,一旦调度实行,就会实行run()方法中的内容。
4.线程中有哪些常用的调度方法?

如start()启用线程等待操作体系调度实行,sleep()让线程休眠一段时间,wait()会让当火线程进入等待,notify()会唤醒一个正在等待的线程。

讲讲wait和notify方法

当线程 A 调⽤共享对象的 wait() ⽅法时,线程 A 会被壅闭挂起,直到线程 B 调用了共享对象的 notify() 方法大概 notifyAll() 方法;
其他线程调用线程A的interrupt() ⽅法,导致线程 A 抛出 InterruptedException 异常。
线程 A 调用共享对象的 wait(timeout) ⽅法后,没有在指定的 timeout 时间内被其它线程唤醒,那么这个方法会 由于超时而返回。
当线程 A 调⽤共享对象的 notify() ⽅法后,会唤醒⼀个在这个共享对象上调用wait 系列方法被挂起的线程。
共享对象上可能会有多个线程在等待,详细唤醒哪个线程是随机的。
讲讲sleep方法

当线程A调用了Thread的sleep方法后,线程A会暂时让出指定时间的实行权。
指定的就寝时间到了之后,线程A会继续参与实行权的争夺。
讲讲yield方法

yield方法是让当火线程让出CPU的利用权,回到就绪状态。但是线程调度器可能会忽略。
讲讲Interrupt方法

interrupt() 方法用于通知线程停⽌,但不会直接终⽌线程,必要线程自行处置惩罚中断标志。 常与 isInterrupted() 或 Thread.interrupted() 配合利用。
5.线程有几种状态?

一样平常6种,new代表线程创建并未启动,runnable代表线程处于就绪或正在运行的状态,由操作体系调度,blocked代表线程被壅闭,可能是获取锁失败,waiting代表等待线程的通知timed_waiting
代表线程等待一段时间,超时会自动恢复,terminated 代表线程执⾏完毕,生命周期结束。

也就是说,线程的周期可以分为五个阶段:新建,就绪,运行,壅闭,停止。线程运行时会根据状态的变化来随时变化。
通过一个表格对线程状态的总结:
状态阐明
NEW当线程被创建后,如通过new Thread(),它处于新建状态。此时,线程已经被分配了必要的资源,但还没有开始执⾏
RUNNABLE当调⽤线程的start()⽅法后,线程进⼊可运⾏状态。在这个状态下,线程可能正在运 ⾏也可能正在等待获取 CPU 时间⽚,详细取决于线程调度器的调度策略。
BLOCKED线程在试图获取⼀个锁以进⼊同步块/⽅法时,如果锁被其他线程持有,线程将进⼊壅闭 状态,直到它获取到锁
WAITING线程进⼊等待状态是由于调⽤了如下⽅法之⼀:Object.wait()或 LockSupport.park()。在等待状态下,线程必要其他线程显式地唤醒,否则不会⾃动 执⾏
TIME_WAITING当线程调⽤带有超时参数的⽅法时,如Thread.sleep(long millis)、 Object.wait(long timeout) 或LockSupport.parkNanos(),它将进⼊超时等待状 态。线程在指定的等待时间过后会⾃动返回可运⾏状态。
TERMINATED当线程的run()⽅法执⾏完毕后,大概由于⼀个未捕获的异常终⽌了执⾏,线程进⼊停止状态。⼀旦线程终⽌,它的⽣命周期结束,不能再被重新启动。
 


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

去皮卡多

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表