文章目录

1、什么是多线程

线程被称为轻量级进程,一个进程会有多个线程。但一个线程是程序执行过程中最小单位,每个程序至少一条线程

2、线程状态

1.初始(NEW):新创建了一个线程对象,但还没有调用start()方法。
2. 运行(RUNNABLE):Java线程中将就绪(ready)和运行中(running)两种状态笼统的称为“运行”。
线程对象创建后,其他线程(比如main线程)调用了该对象的start()方法。该状态的线程位于可运行线程池中,等待被线程调度选中,获取CPU的使用权,此时处于就绪状态(ready)。就绪状态的线程在获得CPU时间片后变为运行中状态(running)。
3. 阻塞(BLOCKED):表示线程阻塞于锁。
4. 等待(WAITING):进入该状态的线程需要等待其他线程做出一些特定动作(通知或中断)。
5. 超时等待(TIMED_WAITING):该状态不同于WAITING,它可以在指定的时间后自行返回。
6. 终止(TERMINATED):表示该线程已经执行完毕。

image.jpg

3、线程同步方法

  • wait():使线程处于一种等待状态,释放所持有的对象锁。
  • sleep():使一个正在运行的线程处于睡眠状态,是一个静态方法,调用它时要捕获InterruptedException异常,不释放对象锁。
  • notify():唤醒一个正在等待状态的线程。注意调用此方法时,并不能确切知道唤醒的是哪一个等待状态的线程,是由JVM来决定唤醒哪个线程,不是由线程优先级决定的。
  • notifyAll():唤醒所有等待状态的线程,注意并不是给所有唤醒线程一个对象锁,而是让它们竞争。

image.jpg

4、创建线程的七种方法==(重要)==

4.1、继承Thread类

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
class ThreadTest {

public static void main(String[] args) {
noAnonymity();
}

// 匿名创建多线程
public static void anonymity(){
for (int i = 0; i < 10; i++) {
new Thread(()->{
System.out.println(Thread.currentThread().getName() + "\t 创建线程");
}).start();
}
}
// 非匿名创建多线程
public static void noAnonymity(){
for (int i = 0; i < 10; i++) {
new MyThread().start();
}
}
}

class MyThread extends Thread{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "\t 创建线程");
}
}

4.2、实现Runnable

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
class RunnableTest {
public static void main(String[] args) {
anonymity();
}

// 匿名创建
public static void anonymity(){
for (int i = 0; i < 10; i++) {
new Thread(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"\t 创建线程");
}
}).start();
}
}

// 非匿名创建
public static void unAnonymity(){
for (int i = 0; i < 10; i++) {
Thread thread = new Thread(new MyRunnable());
thread.start();
}
}
}

class MyRunnable implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"\t 创建线程");
}
}

image.jpg

4.3、实现Callable接口

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class CallableTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
for (int i = 0; i < 10; i++) {
FutureTask<Integer> futureTask = new FutureTask<>(new MyCallableTest());
new Thread(futureTask).start();
System.out.println(futureTask.get());
}
}
}

class MyCallableTest implements Callable<Integer>{
@Override
public Integer call() throws Exception {
System.out.println(Thread.currentThread().getName() +"\t 创建线程");
return 1;
}
}

4.4、创建线程池

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
class ThreadPoolTest {
public static void main(String[] args) {
Anonymity();
}

// 匿名创建
public static void Anonymity(){
ExecutorService es = Executors.newFixedThreadPool(5);
for (int i = 0; i < 10; i++) {
es.execute(new Runnable() {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() +"\t线程创建");
}
});
}
}

// 非匿名创建
public static void unAnonymity(){
ExecutorService es = Executors.newFixedThreadPool(4);
for (int i = 0; i < 10; i++) {
ThreadPool tp = new ThreadPool();
es.submit(tp);
}
// 关闭线程池 如果不关闭,则永远停滞在这里
es.shutdown();
}
}

class ThreadPool implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName() +"\t线程创建");
}
}

4.5、定时器

1
2
3
4
5
6
7
public void schedule(TimerTask task, Date firstTime, long period){}
// task 任务
// firstTime 第一次执行的时间
// 时隔多少时间执行一次

public void schedule(TimerTask task, long delay, long period){}
// delay 执行次任务前,等待时常 如果为0 就是立即执行
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
public class TimerTest {
public static void main(String[] args) {
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
System.out.println("系统启动时间:"+sdf.format(date));
Calendar newTime = Calendar.getInstance();
newTime.setTime(date);
// 加5秒
newTime.add(Calendar.SECOND,5);
Date time = newTime.getTime();
System.out.println("预计定时器启动时间"+sdf.format(time));

Timer timer = new Timer();
// 定时器
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("系统启动后5秒开始执行 , 每隔 2 秒 执行一次");
}
},time,2000);

// 打印时间戳
new Thread(()->{
timer.schedule(new TimerTask() {
@Override
public void run() {
System.out.println("Thread-线程\t 打印时间戳:"+sdf.format(new Date()));
}
},0,1000);
}).start();
}
}

效果:
image.jpg

4.6、Lambda表达式实现

使用 jdk1.8 并行流形式

1
2
3
4
5
6
7
8
9
public class LambdaTest {

public static void main(String[] args) {
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
list.parallelStream().forEach((s)->{
System.out.println(Thread.currentThread().getName()+"\t线程获取到到值为:\t"+s);
});
}
}
1
2
3
4
5
6
7
8
9
main	线程获取到到值为:	5
ForkJoinPool.commonPool-worker-6 线程获取到到值为: 4
ForkJoinPool.commonPool-worker-9 线程获取到到值为: 2
ForkJoinPool.commonPool-worker-13 线程获取到到值为: 6
ForkJoinPool.commonPool-worker-4 线程获取到到值为: 3
ForkJoinPool.commonPool-worker-2 线程获取到到值为: 1
ForkJoinPool.commonPool-worker-11 线程获取到到值为: 7

Process finished with exit code 0

4.7、Spring实现多线程

4.7.1、Maven工程导入Spring相关依赖

这里为直接引用 Spring-Boot 依赖,避免繁琐配置

1
2
3
4
5
6
7
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<version>2.3.7.RELEASE</version>
</dependency>
</dependencies>

4.7.2、新建Java类,开启@EnableAsync注解

开启配置,支持异步任务

1
2
3
4
5
6
7
8
9
10
11
12
package love.study.multithreading.cthread;

import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;

@Configuration
@ComponentScan("love.study.multithreading.cthread")
@EnableAsync
public class SpringConfig {

}

4.7.3、方法类

书写异步执行的方法类(注意方法上需要有@Async——异步方法调用)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package love.study.multithreading.cthread;

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

@Service
public class SpringAsyncService {

@Async
public void AsyncA(){
System.out.println("A is Running");
}

@Async
public void AsyncB(){
System.out.println("B is Running");
}
}

4.7.4、主方法类
1
2
3
4
5
6
7
8
9
10
11
12
package love.study.multithreading.cthread;

import org.springframework.context.annotation.AnnotationConfigApplicationContext;

public class SpringThreadTest {
public static void main(String[] args) {
AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext(SpringConfig.class);
SpringAsyncService bean = ac.getBean(SpringAsyncService.class);
bean.AsyncA();
bean.AsyncB();
}
}

运行结果:有时A在上面 有时B在上面 可知已开启多线程

1
2
B is Running
A is Running

来自: 创建线程的七种方法 (图解 全网最全最详细)-CSDN博客