,多线程的概念
进程:正在运行的程序
线程:它是进程中的一个执行单元(执行路径)
多线程程序:开启多条线程的程序
并发:多个任务在同一时间段同时执行
并行:多个任务同时发生
多线程的好处:让程序的多个任务可以并发执行
CPU执行权的分配方式:
- 分时调度:平均分配CPU的执行权
- 抢占式:多个任务争夺CPU的执行权(随机性),谁获取到了CPU的执行权,谁就执行,Java中的多线程就是采用这种方式
注:没有额外创建线程的Java程序也有两条线程:主函数所在的主线程,垃圾回收器所在的垃圾回收线程
二,创建线程的方式
Thread:线程类
方式一:继承Thread类
步骤:
- 创建类继承Thread
- 重写run()
- 创建该子类的对象
- 调用start()方法开启线程,调用start()会调用run()
注:
- 必须调用start()方法才会开启线程,它会调用重写后的run(),run()方法中定义的功能就是多线程中要并发执行的功能
- 同一个线程对象只能开启一次,否则会发生
IllegalThreadStateException
非法的线程状态异常- 只有当程序中的所有线程全部执行完毕,JVM才会结束
方式二:实现Runnable接口
步骤:
- 创建类实现Runnable接口
- 重写run()
- 创建该实现类对象
- 创建Thread类的对象,将Runnable的实现类对象传入Thread的构造函数
- 调用Thread的start()
以上两种方式都可以通过匿名内部类来实现
// 实现Runnable new Thread(new Runnable(){ @Override public void run() { for(int i = 1; i <= 100;i++){ System.out.println(Thread.currentThread() + "---"+i); } } }).start(); // 继承Thread new Thread(){ @Override public void run() { for(int i = 1; i <= 100;i++){ System.out.println(Thread.currentThread() + "---"+i); } } }.start();
三,线程安全问题
什么是线程安全的:
多个线程操作同一个数据,最终的结果与单线程操作这一数据的结果一致,就称为线程安全
线程安全问题出现的原因:多个线程操作同一个数据
解决办法:使用同步技术
同步的关键字:
synchronized
同步代码块
格式:
synchronized(对象){ 存在线程安全问题的代码 }
注:同步代码块中的对象称为锁对象,这个对象的类型是任意的,但是必须保证这个对象是唯一的
同步函数
格式:
public synchronized 返回类型 方法名(参数){ 存在线程安全问题的代码 }
注:
- 在实现Runnable的方式中,同步函数也有锁对象,锁对象是this
- 在继承Thread的方式中,使用同步函数是无效的,因为锁对象是this,每一个线程对象都有各自的this作为锁,锁对象不唯一。此时需要使用静态同步函数,静态同步函数的锁对象是:
类名.class
public class Demo1 { public static void main(String[] args) { Conductor c1 = new Conductor(); Conductor c2 = new Conductor(); Conductor c3 = new Conductor(); c1.start(); c2.start(); c3.start(); } } class Conductor extends Thread{ static int ticket = 100; static Object object = new Object(); @Override public void run() { for (int i = 1; i <= 100; i++) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } synchronized(object /*Conductor.class*/ ){ if (ticket <= 0) break; System.out.println(Thread.currentThread() + "在售卖" + ticket + "号票"); ticket--; } } } }
Lock
Lock
实现提供了比使用synchronized
方法和语句可获得的更广泛的锁定操作。在JDK1.5中,推出了解决线程安全问题的新办法
Lock接口
,这个接口提供了获取锁和释放锁的方法。方法:
- lock:锁定,获取锁
- unlock:取消锁定,释放锁,归还锁
注:必须保证Lock对象唯一
同步技术的原理:
- 所有线程共同抢夺CPU的执行权,谁抢到了就去
判断锁
是否存在,如果锁存在,则获取锁
并进入同步,如果锁不存在则当前线程处于阻塞状态。- 当获取了锁的线程执行完了同步中的任务,就会
释放锁
,此时所有线程再次共同抢夺CPU的执行权