API中创建线程的两种方式

  • 方式一:继承Thread类

1) 定义子类继承Thread类。

2) 子类中重写Thread类中的run方法。

3) 创建Thread子类对象,即创建了线程对象。

4) 调用线程对象start方法:启动线程,调用run方法。

  • 方式二:实现Runnable接口

1) 定义子类,实现Runnable接口。

2) 子类中重写Runnable接口中的run方法。

3) 通过Thread类含参构造器创建线程对象。

4) 将Runnable接口的子类对象作为实际参数传递给Thread类的构造器中。

5) 调用Thread类的start方法:开启线程,调用Runnable子类接口的run方法。

 

 Java学习笔记-05线程_类名

Java学习笔记-05线程_同步方法_02

 

 

  • 多线程出现了安全问题

问题的原因: 当多条语句在操作同一个线程共享数据时,一个线程对多条语句只执行了一部分,还没有 执行完,另一个线程参与进来执行。导致共享数据的错误。

解决办法: 对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可以 参与执行。

  • 方式一:同步代码块

    synchronized (对象){ // 需要被同步的代码; }

同步代码块:自己指定,很多时候也是指定为this或类名.class

  • 方式二:同步方法

public synchronized void show (String name){ …. }

同步方法的锁:静态方法(类名.class)、非静态方法(this)

  • 方式三:Lock锁

java.util.concurrent.locks.Lock接口是控制多个线程对共享资源进行访问的 工具。锁提供了对共享资源的独占访问,每次只能有一个线程对Lock对象 加锁,线程开始访问共享资源之前应先获得Lock对象。

ReentrantLock 类实现了 Lock ,它拥有与 synchronized 相同的并发性和 内存语义,在实现线程安全的控制中,比较常用的是ReentrantLock,可以 显式加锁、释放锁。

Java学习笔记-05线程_同步方法_03

 

 

Java学习笔记-05线程_共享数据_04

 

  • 线程的通信

    wait() 与 notify() 和 notifyAll()

    wait():令当前线程挂起并放弃CPU、同步资源并等待,使别的线程可访问并修改共享资源,而当 前线程排队等候其他线程调用notify()或notifyAll()方法唤醒,唤醒后等待重新获得对监视器的所有 权后才能继续执行。

    notify():唤醒正在排队等待同步资源的线程中优先级最高者结束等待。

    notifyAll ():唤醒正在排队等待资源的所有线程结束等待.

    这三个方法只有在synchronized方法或synchronized代码块中才能使用,否则会报 java.lang.IllegalMonitorStateException异常。

     Java学习笔记-05线程_子类_05

 

  •  JDK5新增线程创建方式
    • 实现Callable接口:重写call()方法,作为参数传入FurtherTask,并调用其get()方法。再传入Thread,调用start()方法
      • call()有返回值
      • call()可以抛出异常,被外面的操作捕获,获取异常信息
      • Callable支持泛型
    • 使用线程池(多用)
      • 提高响应速度(减少了创建新线程的时间)
      • 降低资源消耗(重复利用线程池中线程,不需要每次都创建)
      • 便于线程管理:核心池的大小、最大线程数、线程最多保持时间
      • ExecutorService:真正的线程池接口 .execute适用于Runnable .submit适用于Callable .shutfdown关闭线程池
      • Executors:工具类、线程池的工厂类,用于创建并返回不同类型的线程池