每一秒钟的时间都值得铭记

0%

Java基础——多线程

线程和进程

进程: 是执行中一段程序,即一旦程序被载入到内存中并准备执行,它就是一个进程。进程是表示资源分配的的基本概念,又是调度运行的基本单位,是系统中的并发执行的单位。

线程: 单个进程中执行中每个任务就是一个线程。线程是进程中执行运算的最小单位。

进程和线程的区别

进程 线程
资源分配的基本概念,调度运行的基本单位,系统中并发执行的单位 执行运算的最小单位,是程序运行的最小单位
一个进程可以有很多个线程 一个线程只能属于一个进程
切换进程系统开销大,创建进程比较消耗性能 切换线程系统开销小,创建线程性能消耗较小
进程有独立的内存空间和系统资源 所有线程共享进程中的内存空间和系统资源
父子进程之间使用进程通信机制进行通信 同一进程的线程使用进程变量来进行通信
进程死亡之后,不会影响其它进程 线程死掉,会导致整个进程死亡

线程的创建方式

在Java中,线程的创建方式一共有4中。

1、继承Thread类,并重写run方法。

1
2
3
4
5
6
7
8
public class MyThread extends Thread{
@Override
public void run() {
for(int i = 0 ;i < 10; i ++) {
System.out.println(getName()+"---"+i);
}
}
}

创建线程,并开启线程。

1
2
3
4
public static void main(String[] args) {
MyThread myThread = new MyThread();
myThread.start();
}

【注意】在开启线程的时候,我们必须要调用线程的start方法,因为start方法才会开辟一条线程通道,而如果调用run方法的话,那么就只是一个普通方法而已。

2、实现Runnable接口。

1
2
3
4
5
6
7
8
public class MyThread2 implements Runnable{
@Override
public synchronized void run() {
for(int i = 0 ;i < 50; i ++) {
System.out.println(Thread.currentThread().getName()+"---"+i);
}
}
}

创建线程,并开启线程。

1
2
3
4
public static void main(String[] args) {
MyThread myThread = new MyThread();
new Thread(myThread).start();
}

【注意】由于Runnable接口是一个函数式接口,所以我们可以使用Lombda表达式来创建线程。

1
2
3
4
5
new Thread(() -> {
for(int i = 0 ;i < 10; i ++) {
System.out.println(Thread.currentThread().getName()+"---"+i);
}
}).start();

3、实现Callable接口。

1
2
3
4
5
6
7
8
9
public class MyThread implements Callable<String>{
@Override
public String call() throws Exception {
for(int i = 0 ;i < 10; i ++) {
System.out.println(Thread.currentThread().getName()+"---"+i);
}
return "mythread";
}
}

创建线程,并开启线程。

1
2
3
4
public static void main(String[] args) {
FutureTask<String> futureTask = new FutureTask<String>(new MyThread());
new Thread(futureTask).start();
}

【注意】由于Callable接口也是一个函数式接口,所以我们也可以使用Lombda表达式来创建线程。

1
2
3
4
5
6
7
8
public static void main(String[] args) {
new Thread(new FutureTask<String>(() -> {
for(int i = 0 ;i < 10; i ++) {
System.out.println(Thread.currentThread().getName()+"---"+i);
}
return "mythread";
})).start();
}

4、线程池

1
2
3
4
5
6
7
8
public static void main(String[] args) {
ExecutorService es = Executors.newFixedThreadPool(5);
es.submit(() -> {
for(int i = 0 ;i < 10; i ++) {
System.out.println(Thread.currentThread().getName()+"---"+i);
}
});
}

【注意】这里直接使用的是Lambda表达式,submit的方法参数可以是Runnable接口和Callable接口的实现类。

Java的线程状态

在Java中,java.lang.Thread包中有一个内部枚举类State,里面列举了Java线程的6中状态。

线程状态 描述
NEW(新建) 刚刚new出来的线程就处于新建状态。
RUNNABLE(运行) 线程调用start方法,并获得CPU的执行时间片。
BLOCKED(锁阻塞) 在使用同步机制的时候,线程没有获取到同步锁,进入锁阻塞。
WAITING(等待) 线程调用wait方法。
TIMED_WAITING(定时等待) 线程调用sleep方法,或者wait和join带时间参数的方法。
TERMINATED(终止) 线程代码执行完毕,线程终止运行。在已终止的线程上调用start方法,会抛出IllegalThreadStateException异常。

线程常用方法

Java中的线程常用方法主要在两个类中,分别是Thread类和Object类。

Thread类

方法 描述
String getName() 返回此线程的名称。
void setName(String name) 将此线程的名称更改为等于参数 name
long getId() 返回此线程的标识符
Thread.State getState() 返回此线程的状态
static Thread currentThread() 返回对当前正在执行的线程对象的引用
static void sleep(long millis) 使当前正在执行的线程以指定的毫秒数暂停(暂时停止执行)
void join(long millis) 等待这个线程死亡最多 millis毫秒
void start() 导致此线程开始执行; Java虚拟机调用此线程的run方法
void run() 如果这个线程使用单独的Runnable运行对象构造,则调用该Runnable对象的run方法; 否则,此方法不执行任何操作并返回

Object类

方法 描述
void wait() 导致当前线程等待,直到另一个线程调用该对象的 notify()方法或 notifyAll()方法。
void wait(long timeout) 导致当前线程等待,直到另一个线程调用 notify()方法或该对象的 notifyAll()方法,或者指定的时间已过。
void notify() 唤醒正在等待对象监视器的单个线程。
void notifyAll() 唤醒正在等待对象监视器的所有线程。

sleep和wait方法的区别

sleep wait
Thread类中的静态方法 Object类中的普通方法,由锁对象调用
sleep方法不会释放锁 wait方法会释放锁
sleep不需要被唤醒 无参的wait方法需要被唤醒
sleep不依赖synchronized关键字 wait方法依赖synchronized关键字

synchronized关键字

在多线程环境下,会有可以发送线程安全问题,导致一些共享数据产生错误,这个时候,我们为了避免线程安全问题,就需要对线程代码进行同步。
synchronized关键字是Java线程中用来保证代码同步的关键字。

原理: synchronized关键字是JVM层面的同步,可以保证在同一时刻,只有一个被synchronized关键字修饰的代码块或方法进入临界区。

synchronized关键字的锁对象

  • 同步方法块:锁对象为括号内的对象。
  • 普通方法:锁对象为当前实例对象。
  • 静态方法,锁对象为该类的字节码对象。

synchronized和Lock的区别

synchronized Lock
Java关键字,JVM层面实现 Java中的一个类,代码实现
只有当synchronized关键字修饰的代码全部执行完毕,才会释放锁。代码发生异常,JVM自动释放锁 使用unlock释放锁,否则会造成死锁
无法判断锁状态 可以判断锁状态
可重入、不可中断、非公平 可重入、可判断、可公平(两者皆可)
适合少量同步代码 适合大量同步代码

思维导图

在这里插入图片描述

坚持原创技术分享,您的支持将鼓励我继续创作!
-------------这是我的底线^_^-------------