线程概念:

面试 #JinDRJ(什么是线程?)

  • 进程:进程会获得操作系统给的资源和CPU调度。
  • 线程:线程是独立获得CPU调度和操作系统资源分派的基本单位。
  • 进程下包含了多个线程。
  • 线程共享其所属进程的资源。
  • 线程间相互竞争CPU调度,是CPU调度的最小单位。
  • 进程间切换开销大,线程间切换开销小。

    线程的状态:

    多线程编程 - 图1

    线程间关系

    并发:
    多个线程在运行,但每个时刻只有一个线程运行。(⭐强调一起出
    并行:
    物理意义上的同时执行。(⭐强调一起执
    同步:
    意义:线程间共享资源,但部分资源一次最好是仅一个线程使用(如打印机打印),所以需要 同步,使得线程排队,而不混乱。
    Java提供的方法:
    1. synchronized(object1){ //阻塞需要加锁,锁的对象应该是括号里配置的 名为 object1 的实例对象
    2. try {
    3. object1.wait(); //阻塞了当前对象对象后面的线程
    4. } catch(InterruptedException e) {
    5. // //
    6. }
    7. }
    1. synchronized(object1) {
    2. object1.notify(); //将唤醒 一个 线程
    3. }
    1. synchronized(this) {
    2. this.notifyAll(); //将唤醒 所有 线程参与竞争
    3. }

创建一个线程

Java 提供了三种创建线程的方法:

  1. 通过实现Runnable接口;
  2. 通过继承Thread类本身;
  3. 通过CallableFuture创建线程。

    实现Runnable接口来创建线程

    具体实现:
  4. RunnableA实现Runnable接口;

  5. 重写run(),这是接口的要求;
  6. new Thread(RunnableA,"threadName");,创建线程;
  7. thread.start();操作,拉起线程。

    Runnable实际代码:

    ```java class RunnableDemo implements Runnable { private Thread t; //其实还是得依托Thread类来拉起线程 这里的实例中的start()函数需要,所以写在类内部 private String threadName;

    RunnableDemo( String name) { //规定名字 threadName = name; }

    @Override public void run() { for(int i = 4; i > 0; i—) {

    1. System.out.println("Thread: " + threadName + ", " + i);

    } }

    public void start () { //本实例封装了new Thread(),且threadName在Main中创建本类时已传入 if (t == null) {

    1. t = new Thread (this, threadName); //重要,
    2. t.start ();

    } } }

public class Main { public static void main(String args[]) { RunnableDemo R1 = new RunnableDemo( “Thread-1”); R1.start(); RunnableDemo R2 = new RunnableDemo( “Thread-2”); R2.start(); }
}

  1. <a name="UQmKY"></a>
  2. #### 继承`Thread`来创建线程
  3. <a name="wmEef"></a>
  4. ##### 具体实现:
  5. 1. 类`ThreadA`继承`Thread`类;
  6. 1. 重写`run()`,实现核心代码;
  7. 1. `new Thread(threadA,"threadName");`实现线程的创建;
  8. 1. `thread.start();`实现线程的拉起。
  9. <a name="YsUq3"></a>
  10. ##### `Thread`实际代码:
  11. ```java
  12. class ThreadDemo extends Thread {
  13. private Thread t;
  14. private String threadName;
  15. ThreadDemo( String name) {
  16. threadName = name;
  17. }
  18. public void run() {
  19. for(int i = 4; i > 0; i--) {
  20. System.out.println("Thread: " + threadName + ", " + i);
  21. }
  22. }
  23. public void start () { //封装了真正拉起线程的 thread.start()
  24. if (t == null) {
  25. t = new Thread (this, threadName);
  26. t.start ();
  27. }
  28. }
  29. }
  30. public class Main {
  31. public static void main(String args[]) {
  32. ThreadDemo T1 = new ThreadDemo( "Thread-1");
  33. T1.start();
  34. ThreadDemo T2 = new ThreadDemo( "Thread-2");
  35. T2.start();
  36. }
  37. }

使得主线程等待子线程的执行:

thread.join();将使得主线程等待名为thread的子线程的执行完成,才继续执行。
所以,

  • 如果多个子线程,一个.start();马上又.join();,将使得程序退变为单线程。
  • 子线程全都先.start();,之后再都.join();,此时,子线程间将异步执行,但主线程等待join()的全部子线程。

    实现Callable接口创建线程


三种创建线程方法的对比:

  • 采用实现RunnableCallable接口的方式创建多线程时,线程类只是实现了Runnable接口或Callable接口,还可以继承其他类。
  • 使用继承Thread类的方式创建多线程时,编写简单(因为最终都是使用new Thread(T,"threadName");拉起线程的),如果需要访问当前线程,直接使用this即可获得当前线程。

Java线程关键字:

volatile(adj.不稳定的)(wa_al-tou)

volatile用法:

public volatile int inc = 0;

volatile意义:
  • 表示这个变量的修改将立即写入主存
  • 表示对这个变量的读取将直接从内存读取,而不是 CPU 寄存器。

    synchronized(v.同步,使在时间上一致)(syn-k_rui-nized)

    synchronized用法:
  • 加锁 代码块:

    1. synchronized(this) { //唤醒也必须加锁,加锁的对象应该是需要执行唤醒操作的对象
    2. this.notify(); //将唤醒 一个 线程
    3. }
  • 加锁 整个函数:

    1. public synchronized void test() {
    2. for (int i = 0; i < 5; i++) {
    3. System.out.println("线程名:"+Thread.currentThread().getName() + ":" + (count++));
    4. }
    5. }

    synchronized意义:
  • 字面意思:同步;

  • 当一个线程在访问synchronized中的内容时,其他想访问 此内容 的线程将被阻塞;
  • 对于普通方法,锁是当前实例对象(this),对于静态同步方法,锁是当前类的class对象。

    Java线程相关方法:

    Thread.sleep(long millisec);:
  • 在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)。

    object.wait();
  • 执行者进入阻塞状态,进入一个和该执行者相关的等待池。

    object.notify();
  • 唤醒一个线程。

    object.notifyAll();
  • 唤醒对象等待池所有线程参与竞争。

Thread.sleep(long millisec);object.wait();的区别:

🐵 #面试 #JinXD
  • Thread.sleep(long millisec);不释放对象锁,object.wait();释放对象锁;
  • object.wait();要搭配object.notify();或者object.notifyAll();来唤醒。