解题思路:
在我看来要实现两个线程交替的打印,
1.t1线程,打印数字1,然后唤醒t2线程,
2.t1线程自己睡眠
3.t2线程打印字母,A,然后唤醒t1线程
上述步骤重复执行
首先用** LockSupport.unpark() LockSupport.park()**的方案来实现,t1、t2 线程必须相互持有,实现代码如下:
public class Test6 {
static String s1 = "123456";
static String s2 = "ABCDEFG";
public static void main(String[] args) throws InterruptedException {
Thread t1 = null;
Thread t2 = null;
MyRunable myRunable2 = new MyRunable();
MyRunable myRunable1 = new MyRunable();
t1 = new Thread(myRunable2);
t2 = new Thread(myRunable1);
myRunable2.setOther(t2);
myRunable2.setS(s2);
myRunable1.setOther(t1);
myRunable1.setS(s1);
t2.start();
Thread.sleep(10);
t1.start();
}
static class MyRunable implements Runnable{
private Thread other;
private String s;
public void setOther(Thread other) {
this.other = other;
}
public void setS(String s) {
this.s = s;
}
@Override
public void run() {
for (int i = 0; i < s.length(); i++) {
System.out.print(s.charAt(i));
LockSupport.unpark(other);
LockSupport.park();
}
}
}
}
这个方案,就是两个线程互相持有,线程的频繁挂起,阻塞,比较消耗系统资源。因为这里其实只是少量的打印,其实看不出什么影响,无所谓啦。
然后是第二种实现方案,用Synchronize+ wait() + notifyAll(), 实现代码如下:
public class Test8 {
static String s1 = "123456";
static String s2 = "ABCDEFG";
public static void main(String[] args) throws InterruptedException {
Object lock1 = new Object();
MyRunable r1 = new MyRunable(lock1, s1);
MyRunable r2 = new MyRunable(lock1, s2);
Thread t1 = new Thread(r1);
Thread t2 = new Thread(r2);
t1.start();
t2.start();
t1.join();
t2.join();
}
static class MyRunable implements Runnable {
private Object mylock;
private String s;
public MyRunable(Object mylock, String s) {
this.mylock = mylock;
this.s = s;
}
@Override
public void run() {
synchronized (mylock) {
for (int i = 0; i < s.length(); i++) {
System.out.println(s.charAt(i));
try {
mylock.notifyAll();
mylock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
这个方案就是两个线程持有了相同的一个object,对同一个objeck加锁。这样两个线程就不会互相持有了,只是持有了同样一个加锁对象。并且Synchronize加锁的效率,是一个锁升级的过程,在争抢不激烈的过程中,应该是一直是自旋锁的一个样子,不会因为调度系统线程资源的而浪费效率。所以,情况应该是好一些。
最后还有一种实现方案:ReentrantLock+ Condition + await() + signal() 代码如下:
public class Test9 {
static String s1 = "1234567";
static String s2 = "ABCDEFG";
public static void main(String[] args) {
Lock lock = new ReentrantLock();
Condition condition1 = lock.newCondition();
Condition condition2 = lock.newCondition();
Runnable r1 = new TestRunable(lock,condition1,condition2,s1);
Runnable r2 = new TestRunable(lock,condition2,condition1,s2);
new Thread(r1).start();
new Thread(r2).start();
}
static class TestRunable implements Runnable{
Lock lock;
Condition condition;
Condition otherCondition;
String s;
public TestRunable(Lock lock, Condition condition, Condition otherCondition, String s) {
this.lock = lock;
this.condition = condition;
this.otherCondition = otherCondition;
this.s = s;
}
@Override
public void run() {
lock.lock();
for (int i = 0; i < s.length(); i++) {
System.out.println(s.charAt(i));
otherCondition.signalAll();
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
otherCondition.signalAll();
lock.unlock();
}
}
}
ReentrantLock 底层的实现 其实也是LockSupport.park(),所以就不过多赘述了。这题的解题思路方案大致就是这么多了。当然,可能还有其他更加有效,写起来更加优美的方案,欢迎大家留言,一起讨论,进步!!!