需求描述
这里考察对线程锁的使用,多线程情况下如何控制各自的执行时间段。
解题思路
我想到的有两种接替思路,一种是使用标志位,一种是使用线程锁。
使用标志位的思路如下:
两个线程一个打印偶数,一个打印奇数,两个线程要交叉执行,所以可以用一个长度为101的数组(第一个位置不用,便于打印的数字和位置保持一致)保存每个线程的执行状态,一个线程执行完毕后在对应位置设置成1,之前前判断数组中前一个位置是否为1,不为1则等待,流程如下:
- 初始化一个全局数组,长度为101,并且每个线程使用num计数,本线程中需要使用的数组的位置,也是需要打印的数组。
- 先让需要输出奇数的线程打印一次,数组中状态为1,0,0,0…,同时num+2。
- 后续两个线程在打印前都判断数组中前一个位置(num-1)是否为1,如果是1,则打印num,同时num+2;否则,等待另外一个线程。
使用线程锁的思路如下:
这种方式就很简单了,直接使用Lock就可以。初始化线程时在线程中设置一个标识,0代表打印偶数,1代表打印奇数。
定义一个全局变量num代表要打印的数字,在线程中判断当前要打印的数字是不是和本线程一直,即奇数=奇数线程,偶数对应偶数线程,如果一直则打印,num++,同时唤醒另外的线程;否则进行等待。
代码编写
思路一
import java.util.concurrent.locks.LockSupport;
/**
* @Function
*
*
* @Update
*
* @Author cc
* @CreateTime 2020年03月04日
*/
public class Day2020304 {
public static void main(String[] args) throws Exception {
Day2020304 main = new Day2020304();
main.run();
}
int[] array = new int[101];
void run() throws Exception {
new Thread(new PrintThread(1)).start();
new Thread(new PrintThread(2)).start();
}
class PrintThread implements Runnable {
int id;
public PrintThread(int id) {
this.id = id;
}
public void run() {
int num = id;
if (id == 1) {
System.out.println("id " + id + " - " + num);
array[num] = 1;
num += 2;
}
while (num <= 100) {
while (array[num - 1] == 0) {
LockSupport.parkNanos(10);
}
System.out.println("id " + id + " - " + num);
array[num] = 1;
num += 2;
}
}
}
}
思路二
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @Function
*
*
* @Update
*
* @Author cc
* @CreateTime 2020年03月04日
*/
public class Day2020304 {
public static void main(String[] args) throws Exception {
Day2020304 main = new Day2020304 ();
main.run();
}
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();
int num = 1;
void run() throws Exception {
new Thread(new PrintThread(0)).start();
new Thread(new PrintThread(1)).start();
}
class PrintThread implements Runnable {
int id;
public PrintThread(int id) {
this.id = id;
}
public void run() {
while (num <= 100) {
lock.lock();
try {
if (num % 2 == id) {
System.out.println("id " + id + " - " + num);
num ++;
condition.signalAll();
} else {
condition.await();
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();
}
}
}
}
}