1.多线程编程
进程是程序的一次执行,是进行资源分配和调度的一个独立单位;
一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。
多线程是多任务的一种特别的形式,但多线程使用了更小的资源开销。
这里定义和线程相关的另一个术语 - 进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程。一个线程不能独立的存在,它必须是进程的一部分。一个进程一直运行,直到所有的非守护线程都结束运行后才能结束。
并发编程的本质:充分利用CPU的资源
2.创建线程的三种方式
Java 提供了三种创建线程的方法:
1.通过实现 Runnable 接口;
2.通过继承 Thread 类本身;
3.通过 Callable 和 Future 创建线程。
3.线程的状态
这里通过查看Java 的Thread.State的源码可知,线程一共有6中状态,具体如下:
NEW, 新生
RUNNABLE,运行
BLOCKED,阻塞
WAITING,等待 无休无止的等下去
TIMED_WAITING,超时等待 过期不候
TERMINATED; 终止
3.synchronized解决并发卖票
这里面单独的抽取出一个Ticket类,里面有属性number表示剩余票数,以及sale卖票的方式,单独作为一个资源类,为了降低耦合性;在创建多线程的内部使用lambda表达式简化代码的编写;一共创建的三个线程,分别命名为A,B,C
package com.xing;
//基本的买票例子
/*
真正的多线程开发 公司中的开发 降低耦合性
* 线程就是一个单独的资源类 没有任何附属的操作
*/
public class SaleTicketDemo01 {
public static void main(String[] args) {
//多线程操作 多个线程操作同一个资源类
Ticket ticket=new Ticket();
//lambda表达式 (参数)->{代码}
new Thread(()->{
for (int i = 0; i < 60; i++) {
ticket.sale();
}
},"A").start();
new Thread(()->{
for (int i = 0; i < 60; i++) {
ticket.sale();
}
},"B").start();
new Thread(()->{
for (int i = 0; i < 60; i++) {
ticket.sale();
}
},"C").start();
}
}
//资源类 OOP编程
class Ticket{
//属性 方法
private int number=50;
//买票的方式 synchronized本质就是排队 锁
public synchronized void sale(){
if (number>0){
System.out.println(Thread.currentThread().getName()+"卖出了第"+(50-(--number))+"票,剩余"+number);
}
}
}
4.Lock解决并发卖票问题
Lock锁三部曲
1.Lock lock=new ReentrantLock();
2.lock.lock();
3.lock.unlock();
package com.xing;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
//基本的买票例子
public class SaleTicketDemo02 {
public static void main(String[] args) {
//多线程操作 多个线程操作同一个资源类
Ticket ticket=new Ticket();
//lambda表达式 (参数)->{代码}
new Thread(()->{for (int i = 0; i < 60; i++) ticket.sale();},"A").start();
new Thread(()->{for (int i = 0; i < 60; i++) ticket.sale();},"B").start();
new Thread(()->{for (int i = 0; i < 60; i++) ticket.sale();},"C").start();
}
}
//Lock锁三部曲
/*
* 1.Lock lock=new ReentrantLock();
* 2.lock.lock();
* 3.lock.unlock();
* */
class Ticket2{
//属性 方法
private int number=50;
Lock lock=new ReentrantLock();
//买票的方式 synchronized本质就是排队 锁
public void sale(){
//加锁
lock.lock();
try {
//业务代码
if (number>0){
System.out.println(Thread.currentThread().getName()+"卖出了第"+(50-(--number))+"票,剩余"+number);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
5.synchronized和Lock的区别
1.synchronized 是内置的java关键字,而Lock是一个Java类;
2.synchronized 无法判断获取锁的状态 ,Lock可以判断是否获取到了锁;
3.synchronized 会自动释放锁 ,Lock必须要手动解锁,如果不释放锁 会死锁;
4.synchronized 线程1(获得锁 阻塞) 线程2(等待 无休止的等带);而Lock则不会一直无限的等待下去,它可以尝试获取锁;
5.synchronized 可重入锁,不可以中断 非公平锁;Lock 可重入锁 可以判断锁 非公平锁(可以自己通过方式设置);
6.synchronized 适合锁少量的代码同步问题 Lock适合锁大量的同步代码。