多线程 首先自问什么是线程
自答 线程就是应用程序启动时候在cpu执行的时候的一个桥梁路径 称之为线程
再问 怎么创建线程
自答 两种方式 一种继承Thread 一种实现Runnable接口
还问 怎么启动线程
针对继承Thread的方式 可以直接Thread t = new Thread(),重写run方法 然后t.start方法启动
再对实现Runnable接口 可以多态Runnable run = new RunnableImpl(),然后在实现
Thread t = new Thread (run),再次t.start 启动 第二种看似多出一步,但是因为是实现接口 所以扩展性 灵活性都要优于继承。
明天再问 准备回家
接着问
线程安全有几种方式?
1.synchronized代码块
2. synchronized方法 静态synchronized方法
3.使用Lock锁
package cn.itcast.day12.demo09;
/**
* @author admin
* @version 1.0.0
* @ClassName RunnableImpl.java
* @Description TODO
* @createTime 2021年09月28日 18:47:00
*/
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* 卖票案例出现了线程安全问题
* 卖出了不存在的票和重复的票
*
* 解决线程安全问题的三种方案:使用lock锁
* java.util.concurrent.locks.Lock接口
*
* Lock实现提供了比使用synchronized方法和语句获得更广泛的锁定操作
* Lock接口中的方法
* void Lock()获取锁
* void unlock() 释放锁
* java.util.concurrent.Locks.ReentrantLock implements Lock接口
*
* 使用步骤
* 1.在成员位置创建一个ReentrantLock对象
* 2.在有可能会出现安全问题的代码前调用Lock接口中的方法Lock获取锁
* 3.有可能会出现安全问题的代码后调用Lock接口中的方法unlock关闭所
*
*
*
*/
public class RunnableImpl implements Runnable {
// 定义一个多线程共享资源
private int ticket = 100;
// 1.在成员位置创建一个ReentrantLock对象
Lock l = new ReentrantLock();
// 设置线程任务 卖票
@Override
public void run() {
// 使用死循环 让卖票操作重复操作
while (true) {
// 2.在有可能会出现安全问题的代码前调用Lock接口中的方法Lock获取锁
l.lock();
// 先判断票是否存在
if (ticket > 0) {
// 提高安全问题出现的概率,让程序睡眠
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "正在卖第" + ticket + "张票");
ticket--;
}
l.unlock();
}
}
}
package cn.itcast.day12.demo09;
/**
* @author admin
* @version 1.0.0
* @ClassName Demo01Ticket.java
* @Description TODO
* @createTime 2021年09月28日 14:23:00
*/
/**
* 模拟卖票案例
* 创建3个线程,同时开启,对共享的票进行出售
*
*/
public class Demo01Ticket {
public static void main(String[] args) {
// 创建Runnable接口的实现类
Runnable run = new RunnableImpl();
// 创建Thread类对象 构造方法中传递Runnable接口的实现类对象
Thread t = new Thread(run);
Thread t1 = new Thread(run);
Thread t2 = new Thread(run);
// 调用start方法开启多线程
t.start();
t1.start();
t2.start();
}
}