Java 多线程基础

1、进程、线程

进程:操作系统分配资源的最小单位

线程:操作系统调动的最小单位

2、使用多线程

  1. 继承 Thread

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
java复制代码public class Run {
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
thread.start();
}
}

class MyThread extends Thread {
@Override
public void run() {
super.run();
System.out.println("thread running");
}

}

输出:

thread running

缺点:不支持多继承
2. 实现 Runnable 接口

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
java复制代码public class Run {
public static void main(String[] args) throws InterruptedException {
MyThread myThread = new MyThread();
Thread thread = new Thread(myThread);
thread.start();
}
}

class MyThread implements Runnable {
@Override
public void run() {
System.out.println("thread running");
}

}

输出:

thread running

优点:“间接”支持多继承
3. 分析多线程的命令

* jps+jstack.exe
* jmc.exe(推荐)
* jvisualvm.exe

3、currentThread() 方法

​ 作用:当前代码块正在被哪个线程调用

​ 例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
java复制代码public class Run {
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
thread.start();
}
}

class MyThread extends Thread {
@Override
public void run() {
System.out.println(currentThread().getName());
}
}

​ 输出:

Thread-0

4、isAlive() 方法

​ 作用:当前线程是否处于活动状态(正在运行、准备开始运行)

​ 例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
java复制代码public class Run {
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
System.out.println("start->" + thread.isAlive());
thread.start();
Thread.sleep(100);
System.out.println("end->" + thread.isAlive());
}
}

class MyThread extends Thread {
@Override
public void run() {
System.out.println("run->" + isAlive());
}
}

​ 输出:

start->false

run->true

end->false

5、sleep(long millis) 方法和sleep(long millis, int nanos) 方法

​ 作用:在指定的时间内(毫秒/毫秒+纳秒)内让“正在执行的线程”休眠,正在执行的线程指 this.currentThread() 返回的线程

​ 例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
java复制代码public class Run {
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
thread.start();
}
}

class MyThread extends Thread {
@Override
public void run() {
System.out.println("start time->"+System.currentTimeMillis());
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("end time-> "+System.currentTimeMillis());
}
}

​ 输出:

start time->1637762721620

end time-> 1637762723623

6、getId() 方法

​ 作用:获得线程的唯一标识

​ 例子:

1
2
3
4
5
6
java复制代码public class Run {
public static void main(String[] args) throws InterruptedException {
Thread thread = Thread.currentThread();
System.out.println(thread.getId());
}
}

​ 输出:

1

7、停止线程

  1. 判断线程是否为停止状态
* `public boolean isInterrupted()`


作用:测试 `currentThread()` 是否已经中断,不清除状态标志


例子:



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
java复制代码public class Run {
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(100);
thread.interrupt();
System.out.println("is thread stop:"+thread.isInterrupted());
System.out.println("is thread stop:"+thread.isInterrupted());
System.out.println("end");
}
}

class MyThread extends Thread {
@Override
public void run() {
super.run();
for (int i = 0; i < 1000; i++) {
System.out.println("i=" + i);
}
}
}
输出: > i=755 > > i=756 > > is thread stop:true > > is thread stop:true > > i=757 > > i=758 * `public static boolean interrupted()` 作用:测试 `this` 关键字所在的类是否已经中断,执行后具有清除状态标志为 false 的功能 例子:
1
2
3
4
5
6
7
8
java复制代码public class Run {
public static void main(String[] args) throws InterruptedException {
Thread.currentThread().interrupt();
System.out.println("is thread stop:" + Thread.interrupted());
System.out.println("is thread stop:" + Thread.interrupted());
System.out.println("end");
}
}
输出: > is thread stop:true > > is thread stop:false > > end 第二次输出 false 的原因: `interrupted()` 具有清除状态的功能,第一次调用时,打印了当前线程被中断,然后将状态清除,此时当前线程的状态为不中断;在第二次调用时,由于上次的调用原因,此时的线程状态已经是不中断,所以打印为 false
  1. 异常法停止线程

例子:

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
java复制代码public class Run {
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(100);
thread.interrupt();
}
}

class MyThread extends Thread {

@Override
public void run() {
super.run();
try {
for (int i = 0; i < 2000; i++) {
if (Thread.interrupted()) {
System.out.println("already stop,exit");
throw new InterruptedException();
}
System.out.println("i=" + i);
}
System.out.println("end");
} catch (InterruptedException e) {
System.out.println("enter exception");
}

}
}

输出:

i=686

i=687

already stop,exit

enter exception
3. ###### stop() 法暴力停止线程

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
java复制代码public class Run {
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(50);
thread.stop();
}
}

class MyThread extends Thread {

@Override
public void run() {
super.run();
for (int i = 0; i < 1000; i++) {
System.out.println("i=" + i);
}
}
}

输出:

i=374

i=375

i=376

i=377

i=378

缺点:

stop() 会释放锁导致数据不一致,已被弃用
4. return 法停止线程

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
java复制代码public class Run {
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(50);
thread.interrupt();
}
}

class MyThread extends Thread {

@Override
public void run() {
while (true) {
if (this.isInterrupted()) {
System.out.println("stop");
return;
}
System.out.println(System.currentTimeMillis());
}
}
}

输出:

1637766071932

1637766071932

1637766071932

stop
5. 在 sleep 状态下停止线程

不管调用顺序,只要 interrupt()stop() 碰到一起就会出现异常

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
java复制代码public class Run {
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(200);
thread.interrupt();
}
}

class MyThread extends Thread {

@Override
public void run() {
try {
System.out.println("thread begin");
Thread.sleep(20000);
System.out.println("thread end");
} catch (InterruptedException e) {
e.printStackTrace();
}

}
}

输出:

thread begin

java.lang.InterruptedException: sleep interrupted

at java.base/java.lang.Thread.sleep(Native Method)  

at demo.MyThread.run(Run.java:18)

8、暂停线程

  1. suspend()resume() 的使用

例子:

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
java复制代码public class Run {
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
thread.start();
Thread.sleep(5000);
thread.suspend();
System.out.println("A=" + System.currentTimeMillis() + " i=" + thread.getI());
Thread.sleep(5000);
System.out.println("A=" + System.currentTimeMillis() + " i=" + thread.getI());

thread.resume();
Thread.sleep(5000);

thread.suspend();
System.out.println("B=" + System.currentTimeMillis() + " i=" + thread.getI());
Thread.sleep(5000);
System.out.println("B=" + System.currentTimeMillis() + " i=" + thread.getI());

}
}

class MyThread extends Thread {

private long i = 0;

public long getI() {
return i;
}

public void setI(long i) {
this.i = i;
}

@Override
public void run() {
while (true) {
i++;
}
}
}

输出:

A=1637855269659 i=8483654775

A=1637855274661 i=8483654775

B=1637855279666 i=17266749694

B=1637855284669 i=17266749694
2. suspend()resume() 的缺点

* 独占
* 数据不完成
  1. suspend()resume() 的替代

suspend() -> wait()

resume() -> notify() / notifyAll()

9、yield() 方法

​ 作用:放弃当前的 CPU 资源,让其他任务去占用 CPU 时间片

​ 例子:

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
java复制代码public class Run {
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
thread.start();
MyThreadYield threadYield=new MyThreadYield();
threadYield.start();
}
}

class MyThread extends Thread {

@Override
public void run() {
long beginTime = System.currentTimeMillis();
for (int i = 0; i < 200000; i++) {

}
long endTime = System.currentTimeMillis();
System.out.println("time:" + (endTime - beginTime));
}
}

class MyThreadYield extends Thread {

@Override
public void run() {
long beginTime = System.currentTimeMillis();
for (int i = 0; i < 200000; i++) {
Thread.yield();
}
long endTime = System.currentTimeMillis();
System.out.println("time:" + (endTime - beginTime));
}
}

​ 输出:

time:1

time:24

10、线程的优先级

设置优先级 public final void setPriority(int newPriority)

预定三个优先级:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
java复制代码    /**
* The minimum priority that a thread can have.
*/
public static final int MIN_PRIORITY = 1;

/**
* The default priority that is assigned to a thread.
*/
public static final int NORM_PRIORITY = 5;

/**
* The maximum priority that a thread can have.
*/
public static final int MAX_PRIORITY = 10;

优先级具有继承性,例如A线程启动B线程,则B的优先级和A一样

11、守护线程

Java中存在两种线程:用户线程(非守护线程)、守护线程

只有进程中不存在非守护线程,则守护线程自动销毁;若存在任何一个非守护线程,守护线程就要继续工作

主线程(main)属于非守护线程

设置守护线程:setDaemon(true),需要在 start() 方法前设置

例子:

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
java复制代码public class Run {
public static void main(String[] args) throws InterruptedException {
MyThread thread = new MyThread();
thread.setDaemon(true);
thread.start();
Thread.sleep(5000);
System.out.println("exit");
}
}

class MyThread extends Thread {

@Override
public void run() {
int i = 0;
while (true) {
i++;
System.out.println("i=" + i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

输出:

i=1

i=2

i=3

i=4

i=5

exit

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%