题目描述:
两个线程交叉打印100以内奇偶数,打印结束后线程正常结束。
思路:
该题考察的是对线程锁的使用,多线程情况下如何控制各自的执行时间段。
思路一:使用标志位
- 使用两个线程交替打印奇数偶数,可以用长度为[101]的数组,(数组0的位置不用,为了保证打印的数字和位置保持一致)
- 先验证数组当前位置的前一个位置的标志位是不是为1,如果是1,则当前线程开始进行打印,在当前线程执行完打印之后,会将数组中的对应的标志位置为1,
- 如果数组当前位置的前一个位置的标志位是0,则当前线程阻塞一定时间,进行等待。
package thread;
import java.util.concurrent.locks.LockSupport;
public class Thread01 {
public static void main(String[] args) throws Exception {
Thread01 main = new Thread01();
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;
}// //Runnable接口的run方法所界定的边界就可以看作是线程代码的边界
public void run(){
int num = id;
if(id == 1){
System.out.println("id" + id + "-" + num);
array[num] =1;
num+=2;
}
while (num <=100){
//判断数组中前一个位置(num-1)是否为1,如果是1则直接打印,如果是0,则将当前线程阻塞指定时间
while (array[num-1] == 0){
//Java中LockSupport.parkNanos与Sleep都可以使当前线程阻塞指定时间,那么除了是否抛出interrupt异常以外
LockSupport.parkNanos(10);
}
System.out.println("id" + id + "-" + num);
array[num] = 1;
num +=2;
}
}
}
}
思路二:使用线程锁
这种方式就很简单了,直接使用Lock就可以。初始化线程时在线程中设置一个标识,0代表打印偶数,1代表打印奇数。
定义一个全局变量num代表要打印的数字,在线程中判断当前要打印的数字是不是和本线程一直,即奇数=奇数线程,偶数对应偶数线程,如果一直则打印,num++,同时唤醒另外的线程;否则进行等待。
package twoTest;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Test14 {
public static void main(String[] args) throws Exception {
Test14 t = new Test14();
t.run();
}
Lock lock = new ReentrantLock();
Condition condition = lock.newCondition();//获取condition对象
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();//唤醒所有等待线程。能够从等待方法返回的线程必须获得与Condition相关的锁。
} else {
condition.await();//造成当前线程在接到信号或被中断之前一直处于等待状态。
}
} catch (Exception e) {
e.printStackTrace();
} finally {
lock.unlock();//解锁
}
}
}
}
}