【Java多线程】Java多线程(2)
前言:
本文内容:实现Callable接口、静态代理模式、Lambda表达式、线程停止、线程休眠sleep、线程礼让yield、线程强制执行join
推荐免费Java多线程讲解视频:【狂神说Java】多线程详解_哔哩哔哩_bilibili
实现Callable接口(仅作了解)
- 实现Callable接口,需要返回值类型;
- 重写call方法,需要抛出异常;
- 创建目标对象;
- 创建执行服务:
ExecutorService service = Executors.newFixedThreadPool(创建线程数量);
- 提交执行:
Future<Boolean> result1 = service.submit(t1);
- 获取结果:
boolean r1 = result1.get();
- 关闭服务:
service.shutdownNow();
1 | package com.jokerdig.demo2; |
静态代理模式
静态代理:(以结婚举例)
- 你:真实角色
- 婚庆公司:代理你,帮你处理结婚事务
- 结婚:实现结婚接口即可
总结:
- 真是对象和代理对象都要实现同一接口;
- 代理对象要代理真实角色;
好处:
-
代理对象可以做很多真实对象做不了的事情;
-
真实对象专注做自己的事情;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50package com.jokerdig.demo2;
/**
* @author Joker大雄
* @data 2021/8/21 - 11:32
**/
public class StaticProxy {
public static void main(String[] args) {
WeddingCompany weddingCompany = new WeddingCompany(new You());
weddingCompany.HappyMarry();
}
}
//结婚接口
interface Marry{
void HappyMarry();
}
//你实现结婚的接口
class You implements Marry{
//自己
public void HappyMarry() {
System.out.println("小王开心的结婚");
}
}
//婚庆公司
class WeddingCompany implements Marry{
private Marry target;
public WeddingCompany(Marry target){
this.target = target;
}
//代理
public void HappyMarry() {
before();
this.target.HappyMarry();
after();
}
//结婚前
private void before() {
System.out.println("结婚之前");
}
//结婚后
private void after() {
System.out.println("结婚之后");
}
}
Lambda表达式
-
λ希腊字母表中排序第十一位的字母,英语名称为Lambda;
-
避免匿名内部类定义过多;
-
其实质属于函数式编程的概念;
1
2
3(params) -> expression[表达式]
(params) -> statement[语句]
(params) -> expression[表达式]a-> System.out.println("it's is lambda"+a);
new Thread(()->System.out.println("多线程学习")).start();
-
为什么要使用lambda表达式
- 避免匿名内部类定义过到;
- 让代码看起来更简介;
- 去掉大量无意义代码,只留下核心的逻辑;
-
也去你会说,我看了Lambda表达式,反而觉得更乱了,看不懂了。多用就能习惯了;
-
理解Functional Interface(函数式接口)是学习Java8 lambda表达式的关键所在;
-
函数时接口的定义:
-
任何接口,如果只包含唯一一个抽象方法,那么他就是一个函数式接口;
1
2
3public interface Runnable{
public abstract void run();
} -
对于函数式接口,我们可以通过lambda表达式来创建该接口的对象;
-
-
简化过程代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63package com.jokerdig.lambda;
/**
* @author Joker大雄
* @data 2021/8/21 - 12:52
**/
//lambda表达式
public class Test1 {
//3.静态内部类
static class Like2 implements Likes{
public void lambda() {
System.out.println("I like lambda2");
}
}
public static void main(String[] args) {
Likes like = new Like();
like.lambda();
like = new Like2();
like.lambda();
//4.局部内部类
class Like3 implements Likes{
public void lambda() {
System.out.println("I like lambda3");
}
}
//调用
new Like3().lambda();
//5.匿名内部类
like = new Likes(){
public void lambda() {
System.out.println("I like lambda4");
}
};
like.lambda();
//6.用lambda简化
like = ()->{
System.out.println("I like Lambda5");
};
like.lambda();
}
}
//1.定义一个函数式接口
interface Likes{
void lambda();
}
//2.实现类
class Like implements Likes{
public void lambda() {
System.out.println("I like lambda");
}
} -
Lambda简化:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33package com.jokerdig.lambda;
/**
* @author Joker大雄
* @data 2021/8/21 - 13:14
**/
public class Test2 {
public static void main(String[] args) {
//lambda表达式简化
ILove love =(int a)->{
System.out.println("I love you"+a);
};
love.love(1);
//1.简化参数类型
love =(a)->{
System.out.println("I love you"+a);
};
love.love(2);
//2.简化括号
love = a ->{
System.out.println("I love you"+a);
};
love.love(3);
//3.简化大括号
love = a -> System.out.println("I love you"+a);;
love.love(4);
}
}
interface ILove{
void love(int a);
}
总结:
- lambda表达式只有一行代码的情况下才能简化成一行的形式,如果有多行,那么就用代码块包裹。
- 前提是接口位函数式接口。
- 多个参数也可以去掉参数类型,要去掉必须加括号。
线程停止
线程状态:
线程方法:
方法 | 说明 |
---|---|
setPriority(int newPriority) | 更改线程的优先级 |
static void sleep(long millis) | 在指定的毫秒数内让当前正在执行的线程休眠 |
void join() | 等待该线程终止 |
static void yield() | 暂停当前正在执行的线程对象,并执行其他前程 |
void interrupt() | 中断线程,尽量不使用该方法 |
boolean isAlive() | 测试线程是否处于活动状态 |
停止线程:
-
不推荐使用JDK提懂得stop(),destroy()方法。(已废弃)
-
推荐线程自己停止下来。
-
建议使用一个标志位进行终止变量,当flag=false,则终止线程运行。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42package com.jokerdig.state;
/**
* @author Joker大雄
* @data 2021/8/21 - 13:48
**/
//测试stop
//1.建议线程正常停止
//2.建议使用标志位
//3.不要使用stop或者destroy等过时方法
public class TestStop implements Runnable{
//设置标志位
private boolean flag=true;
public void run() {
int i=0;
while (flag){
System.out.println("run...Thread"+i++);
}
}
//设置一个公开的方法停止线程,转换标志位
public void stop(){
this.flag = false;
}
public static void main(String[] args) {
TestStop testStop = new TestStop();
new Thread(testStop).start();
for (int i = 0; i < 1000; i++) {
System.out.println("run"+i);
if(i==900){
testStop.stop();
System.out.println(i+"停止线程");
}
}
}
}
线程休眠sleep
线程休眠:
- sleep(时间)指定当前线程阻塞的毫秒数;
- sleep存在异常interruptedException;
- sleep时间达到后线程进入就绪状态;
- sleep可以模拟网络延时,倒计时等;
- 每一个对象都有一个锁,sleep不会释放锁;
模拟倒计时:
1 | package com.jokerdig.state; |
线程礼让yield
线程礼让:
-
礼让线程,让当前正在执行的线程暂停,但不阻塞;
-
将线程从运行状态转为就绪状态;
-
让CPU重新调度,礼让不一定成功!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23package com.jokerdig.state;
/**
* @author Joker大雄
* @data 2021/8/21 - 14:17
**/
//礼让线程,不一定成功
public class TestYield {
public static void main(String[] args) {
MyYield myYield = new MyYield();
new Thread(myYield,"a").start();
new Thread(myYield,"b").start();
}
}
class MyYield implements Runnable{
public void run() {
System.out.println(Thread.currentThread().getName()+"线程开始执行");
Thread.yield();//礼让
System.out.println(Thread.currentThread().getName()+"线程停止执行");
}
}
线程强制执行join
-
Join合并线程,待此线程执行完成后,再执行其他线程,其他线程阻塞;
-
可以想象成插队;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31package com.jokerdig.state;
/**
* @author Joker大雄
* @data 2021/8/21 - 14:23
**/
//测试Join方法
public class TestJoin implements Runnable{
public static void main(String[] args) throws InterruptedException {
TestJoin testJoin = new TestJoin();
Thread thread = new Thread(testJoin);
//主线程
for (int i = 1; i < 200; i++) {
if(i==100){
//start放这里防止vip线程提前同普通线程一起启动
thread.start();
thread.join();//插队
}
System.out.println("普通线程"+i);
}
}
//插队
public void run() {
for (int i = 1; i < 500; i++) {
System.out.println("线程vip来了"+i);
}
}
}
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Hey,Joker!
评论
ValineTwikoo