多线程
线程
术语
与多任务有关。
并行:
与系统相关 多个任务同时执行。 多核
并发:
分布式系统有关系。
互联网项目中: 高并发 高性能 高可用 服务器有关 tomcat 100 mysql: 151
在吃饭期间 有电话进来了
你一边吃饭 一边打电话 并行
你吃了一口饭 停下来 去说话 并发
同步:
一个任务的执行必须等待其他任务的结束。
异步:
这个任务的执行 不必要等到其他任务结束。 异步请求(前台页面)
下订单:
支付 银行卡扣钱 安排物流 单号
阻塞:
同步必然会有阻塞。
Scanner 阻塞的状态 System.in InputStream IO: bio
非阻塞:
异步必然就不会阻塞。 NIO
进程:
相对于系统而言 占据cpu 内存 等同于系统内部的一个应用程序。 EV IDEA
线程:
在我们进程里面 更小的程序执行单元 线程
QQ应用程序 开启很多个窗口 多个线程 cpu上下文时间片
一个进程有多个线程。线程与线程之间是相互独立的。共享进程资源。
同步阻塞,相当于一个线程在等待。
同步非阻塞,相当于一个线程在正常运行。
异步阻塞,相当于多个线程都在等待。 路上红灯
异步非阻塞,相当于多个线程都在正常运行。 绿灯
多线程
在java程序 程序执行的话 至少有2个线程。 主线程 main GC 垃圾守护线程 支持多线程。
单线程 vs 多线程
单:
有且只有一个任务进行执行。 cpu只做一件事情。 浪费cpu
多线程:
在同一个时间内 执行了多个任务的 提高了cpu的资源利用率的问题。
下载视频:
一个个下:
同一时间可以下载多个
弊端:
有可能会出现线程安全。
Thread
public class Thread extends Object implements Runnable
static class Thread.State 线程的状态
static int MAX_PRIORITY 10
static int MIN_PRIORITY 1
static int NORM_PRIORITY 5
理论上就是级别越高 可能优先被执行的概率就越大 实际上: 参照线程抢占cpu的效率
Thread(Runnable target)
Thread(Runnable target, String name)
Thread(String name)
static Thread currentThread() 获得当前正在运行的线程
long getId()
String getName()
int getPriority()
Thread.State getState()
void setName(String name)
void setPriority(int newPriority)
void join() 等待当前线程死亡
void join(long millis)
void run() 禁止手动调用 线程逻辑运行 会被自动执行的
static void sleep(long millis) 休眠 并不释放锁 线程调度 超时了会自动醒过来
void start() 启动线程 自动调用run方法逻辑
static void yield() 当前线程舍弃抢占cpu的机会 又会立马处于就绪状态
//必须是同一个锁对象(监视器) 任意一个对象都可以充当锁对象
//synchornized
void wait() 当前线程一直处于等待状态 不会自动醒过来 会自动释放锁 其它线程唤醒他
void wait(long timeout) 当前线程在指定时间内等待 会自动释放锁 超时了会自动醒过来/其它线程唤醒他
void wait(long timeout, int nanos)
void notify() 唤醒随机的一个wait的线程
void notifyAll() 唤醒所有的
创建多线程
继承Thread
public class 类 extends Thread{
//重写父类的run方法
}
实现Runnable接口
public class 类 implements Runnable{
//重写父类的run方法
}
#### 实现Callable<T>接口
> 另外一个线程的执行 必须等待你第一个结束才去执行 (需要获得第一个线程运算完之后的结果)
```java
public class 类 implements Callable<>{
//重写父类的call方法
}
模拟:
取钱 存钱
public class MoneyCallable implements Callable<Double> {
//余额
private double balance = 1000;//银行卡余额
private boolean flag = false;//取钱/存钱 标识
private double money;//取钱/存钱
@Override
public Double call() throws Exception {
//类似于run
if (!flag) {
System.out.println(Thread.currentThread().getName() + "取了王五" + money + "钱");
balance -= money;
} else {
balance += money;
System.out.println(Thread.currentThread().getName() + "转给王五" + money + "钱");
}
return balance;
}
public MoneyCallable(boolean flag, double money) {
this.flag = flag;
this.money = money;
}
public double getBalance() {
return balance;
}
}
其它方式
public static void main(String[] args) {
new Thread(new Runnable() {
@Override
public void run() {
}
}).start();
new Thread(() -> {
System.out.println("dgdfgddfg");
}).start();
new Thread(new FutureTask<Integer>(new Callable<Integer>() {
@Override
public Integer call() throws Exception {
return null;
}
})).start();
new Thread(new FutureTask<String>(() -> {
return "";
})).start();
}
线程安全
synchronized(同步锁)
同步锁 悲观锁 互斥锁
1.1 同步代码块(自动上锁+自动释放锁)
synchronized(锁对象){
//容易出现线程安全的逻辑
}
@Override
public void run() {
//多个窗口卖30张票
while (ticketsNum > 0) {
synchronized ("锁") {
System.out.println(Thread.currentThread().getName() + "卖了第" + ticketsNum + "张票");
ticketsNum--;
}
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
1.2 同步方法 StringBuffer Vector
public void synchronized a(){}
public class SaleTicketRunnable implements Runnable {
// private volatile int ticketsNum = 30;
private int ticketsNum = 30;
@Override
public void run() {
//多个窗口卖30张票
while (ticketsNum > 0) {
abc();
try {
TimeUnit.MILLISECONDS.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//锁对象? 同一个对象 this saleTicketRunnable1
public synchronized void abc() {
System.out.println(Thread.currentThread().getName() + "卖了第" + ticketsNum + "张票");
ticketsNum--;
}
}
2. Lock
互斥锁 ReentrantLock