Java基础-多线程

一、并发与并行

并发:交替执行。指两个或多个事件在同一个时间段内发生。(一个人吃两个馒头)

并行:同时执行。指两个或多个事件在同一时刻发生。(两个人吃两个馒头)

二、线程与进程

进程:是指一个内存中运行的应用程序。一个应用程序可以同时运行多个进程。

线程:线程是进程中的一个执行单元,负者当前进程中程序的执行,一个进程中至少有一个线程。一个进程中是可以有多个线程的,这个应用程序也可以称为多线程程序。

线程调度:
        分时调度:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间。
        抢占式调度:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个(线程随机性 ),Java使用的是抢占式调度。

三、创建多线程程序的第一种方式:创建Thread类的子类

java.lang.Thread类:是描述线程的类。

构造方法:

public Thread();    // 分配一个新的线程对象。
public Thread(String name);    // 分配一个指定名字的新的线程对象。
public Thread(Runnale target);    // 分配一个带有指定目标的新的线程对象。
public Thread(Runnale target,String name);    // 分配一个带有指定目标的新的线程对象并指定名字。

常用方法:

public String getName();    // 获取当前线程名称。
public void setName();    // 改变线程名称。
public void start();    // 导致此线程开始执行,java虚拟机调用此线程的run方法。
public void run();    // 此线程要执行的任务在此处定义代码。
public static void sleep(long millis);    // 使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)。
public static Thread currentThread();    // 返回当前正在执行的线程对象。

四、创建多线程程序的第二种方式:实现Runnale接口

实现步骤:        
        1 创建一个Runnable接口的实现类
        2. 在实现类中重写Runnable接口的run方法,设置线程任务
        3. 创建一个Runnable接口的实现类对象
        4. 创建Thread类对象,构造方法中传递Runnable接口的实现类对象
        5. 调用Thread类中的start方法,开启新的线程执行run方法

五、线程安全

1. 线程安全与线程同步

使用多个线程访问同一资源的时候,且多个线程中对资源有写的操作,就容易出现线程安全问题。

为了保证每个线程能正常执行原子操作,java引入了线程同步机制。

三种方式完成同步操作:
        1. 同步代码块
        2.同步方法
        3. 锁机制

2. 同步代码块

同步代码块:synchronized 关键字可以用于方法中的某个区块,表示只对这个区块的资源实行互斥访问。
格式:

synchronized(锁对象){
    可能会出现线程安全问题的代码(访问了共享数据的代码)
}

注意:
        1. 通过代码块中的锁对象,可以使用任意的对象
        2. 但是必须保证多个线程使用的锁对象是同一个
        3. 锁对象的作用:把同步代码块锁住,只让一个线程在同步代码块中执行

3. 同步方法

使用步骤:       
        1. 把访问了共享数据的代码抽取出来,放到一个方法中
        2. 在方法上添加synchronized修饰符

格式:

修饰符 synchronized 返回值类型 方法名(参数列表){
    可能会出现线程安全问题的代码(访问了共享数据的代码)
}

4. Lock锁

java.util.concurrent.locks.Lock接口

Lock 实现了提供比使用synchronized 方法和语句可获得更广泛的锁定操作。

Lock接口中的方法:

void lock();    // 获取锁
void unlock():    // 释放锁

java.util.concurrent.locks.ReentrankLock implements Lock接口

使用步骤:
        1. 在成员位置创建一个ReenrantLock对象
        2. 在可能会出现安全问题的代码前调用Lock接口中的方法lock获取锁
        3. 在可能会出现安全问题的代码后调用Lock接口中的方法unlock释放锁

六、线程状态

线程状态及导致状态发生条件
NEW(新建):线程刚被创建,但是并未启动。还没调用start方法。

Runnable(可运行):线程可以在java虚拟机中运行的状态,可能正在运行自己的代码,也可能没有,这取决于操作系统处理器。

Blocked(锁阻塞):当一个线程试图获取第一个对象锁,而该对象锁被其他的线程持有,则该线程进入Blocked状态;当该线程持有锁时,该线程将变成Runnable状态。

Waiting(无限等待):一个线程在等待另一个线程执行一个(唤醒)动作时,该线程进入Waiting状态。进入这个状态后市不能被自动唤醒的,必须等待另一个线程调用notify或者notifyAll方法才能唤醒。

Timed Waiting(计时等待):同waiting状态,有几个方法有超时参数,调用他们进入Timed Waiting状态。这一状态将一直保持到超时期满或者接收到唤醒通知。带有超时参数的常用方法有Thread.sleep、Object.wait

Teminated:因为run方法正常退出而死亡,或者因为没有捕获的异常终止了run方法而死亡。

七、线程间通信

1. 概念:
        多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同。

2. 为什么要处理线程间通信:
        多个线程并发执行时,在默认情况下CPU是随机切换线程的,当我们需要多个线程共同完成一件任务,并且我们希望有规律的执行,那么线程之间需要一些协调通信。
3. 如何保证线程间通信有效利用资源:等待唤醒机制

八、线程池

1. 概念:
        其实就是一个容纳多个线程的容器,其中的线程可以反复使用,省去了频繁创建线程对象的操作,无需反复创建线程而消耗过多资源。

2. 线程池(JDK1.5之后)使用:

java.util.concurrent.Executors:线程池的工厂类,用来生成线程池。

Exccutors类中的静态方法:
        static ExecutorsService newFixedThreadPool (int nThreads) :创建一个可重用固定线程数的线程池 
        参数:int nThreads:创建线程池中包含的线程数量
        返回值:ExecutorService接口,返回的是ExecutorService接口的实现类对象,我们可以使用ExecutorService接口接收(面向接口编程)。

java.util.concurrent.ExecutorService:线程池接口
        用来从线程池中获取线程,调用start方法,执行线程任务:submit(Runnable task)提交一个Runnable任务用于执行
        关闭/销毁线程池的方法:void shutdown()

3. 线程池的使用步骤:
        1. 使用线程池的工厂类Executor里提供的静态方法newFixedThreadPool生产一个指定线程数量的线程池。
        2. 创建一个类,实现Runnable接口,重写run方法,设置线程任务。
        3. 调用ExecutorService中的方法submit,传递线程任务(实现类),开启线程,执行run方法。
        4. 调用ExecutorService中的方法shutdown销毁线程池(不建议执行)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值