Java并发

Java多线程入门 类和接口

JDK提供了Thread类和Runnalble接口来让我们实现自己的“线程”类

继承Thread类,并重写run方法

构造函数:

1
2
3
4
5
6
7
8
9
private void init(ThreadGroup g, Runnable target, String name,
long stackSize, AccessControlContext acc,
boolean inheritThreadLocals)
public Thread(Runnable target) {
init(null, target, "Thread-" + nextThreadNum(), 0);
}
public Thread(Runnable target, String name) {
init(null, target, name, 0);
}

Thread类常用方法

  1. currentThread():静态方法,返回对当前正在执行的线程对象的引用;
  2. start():开始执行线程的方法,java虚拟机会调用线程内的run()方法;
  3. yield():yield在英语里有放弃的意思,同样,这里的yield()指的是当前线程愿意让出对当前处理器的占用。这里需要注意的是,就算当前线程调用了yield()方法,程序在调度的时候,也还有可能继续运行这个线程的;
  4. sleep():静态方法,使当前线程睡眠一段时间;
  5. join():使当前线程等待另一个线程执行完毕之后再继续执行,内部调用的是Object类的wait方法实现的;

Runnable接口

实现Runnable接口的run方法

Runnable是一个函数式接口,这意味着我们可以使用Java 8的函数式编程来简化代码

1
2
3
new Thread(() -> {
System.out.println("Java 8 匿名内部类");
}).start();

Thread类 对比 Runnable接口

  1. 由于Java“单继承,多实现”的特性,Runnable接口使用起来比Thread更灵活。
  2. Runnable接口出现更符合面向对象,将线程单独进行对象的封装
  3. Runnable接口出现,降低了线程对象和线程任务的耦合性
  4. 如果使用线程时不需要使用Thread类的诸多方法,显然使用Runnable接口更为轻量

Redspider社区的《深入浅出Java多线程》

链接

简介:站在巨人的肩上,我们可以看得更远。本书内容的主要来源有博客、书籍、论文,对于一些已经叙述得很清晰的知识点我们直接引用在本书中;对于一些没有讲解清楚的知识点,我们加以画图或者编写Demo进行加工;而对于一些模棱两可的知识点,本书在查阅了大量资料的情况下,给出最合理的解释

代码题目

1114. 按序打印

多线程题目

循环打印abcd十次

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
public class SynchronizedPrinter {
private static final Object lock = new Object();
private static int currentState = 0;
private static int count = 0;

public static void main(String[] args) {
new Thread(() -> printLetter('a', 0), "A").start();
new Thread(() -> printLetter('b', 1), "B").start();
new Thread(() -> printLetter('c', 2), "C").start();
new Thread(() -> printLetter('d', 3), "D").start();
}

private static void printLetter(char letter, int targetState) {
for (int i = 0; i < 10; i++) {
synchronized (lock) {
while (currentState != targetState) {
try {
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.print(letter);
currentState = (targetState + 1) % 4;
if (targetState == 3) count++;
lock.notifyAll();
}
}
}
}
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
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ReentrantLockPrinter {
private static final Lock lock = new ReentrantLock();
private static final Condition condition = lock.newCondition();
private static int currentState = 0;
private static int count = 0;

public static void main(String[] args) {
new Thread(() -> printLetter('a', 0), "A").start();
new Thread(() -> printLetter('b', 1), "B").start();
new Thread(() -> printLetter('c', 2), "C").start();
new Thread(() -> printLetter('d', 3), "D").start();
}

private static void printLetter(char letter, int targetState) {
for (int i = 0; i < 10; i++) {
lock.lock();
try {
while (currentState != targetState) {
condition.await();
}
System.out.print(letter);
currentState = (targetState + 1) % 4;
if (targetState == 3) count++;
condition.signalAll();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
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
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class AlternatePrint { // ReentrantLock Condition写法
private static int count = 1; // 共享计数器
private static final int MAX_COUNT = 20; // 最大打印次数(每个字母算作一次)
private static final ReentrantLock lock = new ReentrantLock();
private static final Condition conditionA = lock.newCondition();
private static final Condition conditionB = lock.newCondition();
private static final Condition conditionC = lock.newCondition();
private static final Condition conditionD = lock.newCondition();

public static void main(String[] args) {
new Thread(() -> printLetter("a", conditionA, conditionB), "A").start();
new Thread(() -> printLetter("b", conditionB, conditionC), "B").start();
new Thread(() -> printLetter("c", conditionC, conditionD), "C").start();
new Thread(() -> printLetter("d", conditionD, conditionA), "D").start();

lock.lock();
try {
conditionA.signal();
} finally {
lock.unlock();
}
}

public static void printLetter(String name, Condition currentCondition, Condition nextCondition) {
while (true) {
lock.lock();
try {
// 等待被唤醒
currentCondition.await();
if (count > MAX_COUNT) {
// 如果超过最大打印次数,唤醒下一个线程并退出
nextCondition.signal();
break;
}
// 打印数字
System.out.println(name + " = " + count);
count++;
// 唤醒下一个线程
nextCondition.signal();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}