Java多线程

说不上技术分享,只能算是学习记录

创建一个线程

Java 提供了三种创建线程的方法:

  • 通过实现 Runnable 接口;
  • 通过继承 Thread 类本身;
  • 通过 Callable 和 Future 创建线程。

通过实现 Runnable 接口来创建线程

实现Runnable接口,重写run方法,调用start方法

实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class Thread2 implements Runnable{

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

public static void main(String[] args) {
Thread2 t2=new Thread2();
new Thread(t2).start();
for (int i = 0; i <1000; i++) {
System.out.println("now"+i);
}
}
}

通过继承Thread来创建线程

继承Thread类,重写run方法,调用start方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class Thread1 extends Thread{
@Override
public void run() {
for (int i = 0; i < 20; i++) {
System.out.println("t"+i);
}
}

public static void main(String[] args) {
Thread1 t1=new Thread1();
t1.start();
for (int i = 0; i <1000; i++) {
System.out.println("now"+i);
}
}
}

通过 Callable 和 Future 创建线程

    1. 创建 Callable 接口的实现类,并实现 call() 方法,该 call() 方法将作为线程执行体,并且有返回值。
    1. 创建 Callable 实现类的实例,使用 FutureTask 类来包装 Callable 对象,该 FutureTask 对象封装了该 Callable 对象的 call() 方法的返回值。
    1. 使用 FutureTask 对象作为 Thread 对象的 target 创建并启动新线程。
    1. 调用 FutureTask 对象的 get() 方法来获得子线程执行结束后的返回值。

创建线程的三种方式的对比

    1. 采用实现 Runnable、Callable 接口的方式创建多线程时,线程类只是实现了 Runnable 接口或 Callable 接口,还可以继承其他类。
    1. 使用继承 Thread 类的方式创建多线程时,编写简单,如果需要访问当前线程,则无需使用 Thread.currentThread() 方法,直接使用 this 即可获得当前线程。

线程的几个主要概念

在多线程编程时,你需要了解以下几个概念:

  • 线程同步
  • 线程间通信
  • 线程死锁
  • 线程控制:挂起、停止和恢复

Sleep

休眠,单位:毫秒

Yield

礼让,但不一定成功

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
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 {

@Override
public void run() {
System.out.println(Thread.currentThread().getName() + "线程开始执行");
Thread.yield();
System.out.println(Thread.currentThread().getName() + "线程停止执行");
}
}

Join

强制执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class TestJoin implements Runnable{
public static void main(String[] args) throws InterruptedException {
TestJoin testJoin=new TestJoin();
Thread thread=new Thread(testJoin);
thread.start();

for (int i = 0; i < 500; i++) {
if(i==200) {
thread.join();
}
System.out.println("main"+i);
}
}

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

同步

synchronized关键字

Lock

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
import java.util.concurrent.locks.ReentrantLock;

public class TestLock {
public static void main(String[] args) {
TestLock2 testLock2=new TestLock2();
new Thread(testLock2).start();
new Thread(testLock2).start();
new Thread(testLock2).start();
}
}

class TestLock2 implements Runnable {
int ticketNum = 10;

//定义Lock锁
private final ReentrantLock lock = new ReentrantLock();

@Override
public void run() {
while (true) {
try {
lock.lock();//加锁
if (ticketNum > 0) {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(ticketNum--);
} else {
break;
}
} finally {
lock.unlock();//解锁
}
}
}
}

线程池

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public class TestPool {
public static void main(String[] args) {
//创建服务,创建线程池
//newFixedThreadPool 参数:线程池大小
ExecutorService service = Executors.newFixedThreadPool(10);
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
//关闭
service.shutdown();
}
}

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

参考

https://www.bilibili.com/video/BV1V4411p7EF