笔记大纲
-
进程与线程
- 进程&线程
- 线程的状态
- wait&sleep
- 并发&并行
-
Lock接口
- Synchronzied
- Lock
- Synchronzied&Lock区别
- 售票案例代码
-
java8特性
- Lambda表达式
- 接口里存在的实现方法
- 案例代码
JUC:java.util.concurrent在并发编程中使用的工具类
一、进程与线程
1.什么是进程、线程?
进程:进程是一个具有一定独立功能的程序关于某个数据集合的一次运行活动,它是操作系统动态执行的基本单元。
线程:通常在一个进程中可以包含若干个线程,当然一个进程中至少有一个线程,不然没有存在的意义。线程可以利用进程所拥有的资源,在引入线程的操作系统中,通常都是把进程作为分配资源的基本单位,而把线程作为独立运行和独立调度的基本单位,由于线程比进程更小,基本上不拥有系统资源,故对它的调度所付出的开销就会小得多,能更高效的提高系统多个程序间并发执行的程度。
2.线程的状态
new
(新建)、Blocked
(阻塞)、runnable
(准备就绪)、waiting
(不见不散)、timed_waiting
(过时不候)、terminated
(终结)
public enum State {
/**
* Thread state for a thread which has not yet started.
*/
NEW,(新建)
RUNNABLE,(准备就绪)
BLOCKED,(阻塞)
WAITING,(不见不散)
TIMED_WAITING,(过时不候)
TERMINATED;(终结)
}
3.wait、sleep的区别?
相同点:都是当前线程暂停(在哪睡在哪醒)。
不同点:
wait:放开资源和锁,外面的资源可以争抢;
sleep:拿着资源和锁,超时就会自动唤醒。
4.什么是并发?什么是并行?
并发:同一时刻,同时争抢一个资源(同一时刻多个线程在访问同一个资源,多个线程对一个点),常见应用场景:春运秒杀;
对于开发人员,我们需要考虑到系统功能、数据质量、并发压力<例如Linux
上的ab
工具,常见的超买问题,用Redis和乐观锁和事务解决,还是会引发一系列问题,最终是用连接池解决超时问题>;
并行:同一时刻,做不同的事(多项工作一起执行,之后再汇总),常见应用场景:泡方便面,电水壶烧水,一边撕调料倒入桶中。
二、Lock接口
1.Synchronzied
1.1.多线程编程模板上
线程 操作 资源类
高内聚低耦合
1.2.实现步骤
(1)创建资源类
(2)资源类里创建同步方法、同步方法块
2.Lock
2.1.Lock接口的实现ReentrantLock可重入锁
//参考JDK1.8-API文档
class X {
private final ReentrantLock lock = new ReentrantLock();
// ...
public void m() {
lock.lock(); // block until condition holds
try {
// ... method body
} finally {
lock.unlock()
}
}
}
2.2.创建线程的方式
(1)继承Thread
public class TestXXX extends Thread //java是单继承,资源宝贵,要用接口方式
(2)new Thread()
Thread t1 = new Thread();
t1.start();
(3)Thead (Runnable target,String name)
Thead (Runnable target,String name) //构造参数(接口、线程名--方便日志的详细输出)
2.3.实现Runnable接口方法
(1)新建类实现Runnable接口
class MyThread implements Runnable//新建类实现runnable接口
new Thread(new MyThread,...)//这种方法会新增类
(2)匿名内部类
// 这种方法不需要创建新的类,可以new接口
new Thread(new Runnable() {
@Override
public void run() {
}
}, "your thread name").start();
(3)lambda表示式(最简单)
//这种方法代码更简洁精炼
new Thread(() -> {
}, "your thread name").start();
3.Synchronzied与Lock的区别
Synchronzied能实现的Lock都能实现;
Lock比Synchronzied更灵活,自定义锁的范围,性能更高(可分配Condition);
Synchronzied不同手动上锁,Lock需要手动上锁、解锁。
4.售票案例代码
package com.lindaxia.gmall.gmallzookeeper.gmallzookeeperdemo;
import java.util.concurrent.locks.ReentrantLock;
class Ticket{
private int number = 30;
private final Lock lock = new ReentrantLock();
/* //synchronized类似表锁
public synchronized void sale() {
int a = 1;
synchronized ()
if (number > 0) {
System.out.println(Thread.currentThread().getName()
+"\t已卖出"+number--+"\t号票,还剩"+number);
}
}*/
//资源类
public void sale() {
lock.lock();
try {
if (number > 0) {
System.out.println(Thread.currentThread().getName()
+ "\t已卖出" + number-- + "\t号票,还剩" + number);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();//解锁
}
}
}
/**
* 卖票程序:三个售票员 卖出30张票
* 线程 操作 资源类
* 高内聚低耦合
*/
public class SaleTicket {
public static void main(String[] args) {
Ticket ticket = new Ticket();
new Thread(() -> {for (int i = 1; i < 40; i++)ticket.sale();}, "AA").start();
new Thread(() -> {for (int i = 1; i < 40; i++)ticket.sale();}, "BB").start();
new Thread(() -> {for (int i = 1; i < 40; i++)ticket.sale();}, "CC").start();
/* //创建线程
new Thread(new Runnable(){
@Override
public void run() {
for (int i = 0; i < 40; i++) {
ticket.sale();
}
}
},"AA").start();
new Thread(new Runnable(){
@Override
public void run() {
for (int i = 0; i < 40; i++) {
ticket.sale();
}
}
},"BB").start();*/
}
}
三、java8特性
1.Lambda表达式
Lambda 是一个匿名函数,我们可以把 Lambda表达式理解为是一段可以传递的代码(将代码像数据一样进行传递)。可以写出更简洁、更灵活的代码。作为一种更紧凑的代码风格,使Java的语言表达能力得到了提升。
Lambda 表达式在Java 语言中引入了一个新的语法元素和操作符。这个操作符为 “->” , 该操作符被称为 Lambda 操作符或剪头操作符。它将 Lambda 分为两个部分:
左侧:指定了 Lambda 表达式需要的所有参数;
右侧:指定了 Lambda 体,即 Lambda 表达式要执行的功能。
1.1.表达式要求
lambda表达式,如果一个接口只有一个方法,可把方法名省略
Foo foo = () -> {System.out.println("****hello lambda");};
1.2.表达式写法
拷贝小括号(),写死右箭头->,落地大括号{…}(省略方法与方法名)
1.3.函数式接口
lambda
表达式,必须是函数式接口,必须只有一个方法!如果接口只有一个方法java默认它为函数式接口。
为了正确使用Lambda
表达式,需要给接口加个注解:@FunctionalInterface
,如有两个方法,立刻报错!
2.接口里是否能有实现方法?
2.1.default方法
//接口里在java8后可以有接口的实现,default方法默认实现,可以有多个
default int div(int x,int y) {
return x/y;
}
2.2.静态方法(类方法)
//静态方法实现:接口新增 ,可以有多个
public static int sub(int x,int y){
return x-y;
}
3.案例代码
package com.lindaxia.gmall.gmallzookeeper.gmallzookeeperdemo;
@FunctionalInterface //函数式接口注解
interface Foo {
public int add(int a, int b);
default int div(int a, int b) { //default方法
return a / b;
}
public static int sub(int a, int b) {//静态方法
return a - b;
}
}
/**
* Lamnbda Express (函数式编程)
* 拷贝小括号(),写死右箭头-->,落地大括号{}
*/
public class LambdaDemo {
public static void main(String[] args) {
/* Foo foo1 = new Foo() {
@Override
public int add(int x, int y) {
System.out.println("Hello,lindaxia");
return x + y;
}
};
System.out.println(foo1.add(6, 6));
}*/
Foo foo = (int a, int b) -> {
System.out.println("Hello,lindaxia");
return a + b;
};
System.out.println(foo.add(6, 6));
System.out.println(foo.div(6, 6));
System.out.println(Foo.sub(6, 6));
}
}
☝上述分享来源个人总结,如果分享对您有帮忙,希望您积极转载;如果您有不同的见解,希望您积极留言,让我们一起探讨,您的鼓励将是我前进道路上一份助力,非常感谢!我会不定时更新相关技术动态,同时我也会不断完善自己,提升技术,希望与君同成长同进步!
☞本人博客:https://coding0110lin.blog.csdn.net/ 欢迎转载,一起技术交流吧!