1、使用volatile变量来控制,不需要用锁,效率较高但是比较耗资源
public class CrossNum {
public volatile int num = 1;
public volatile boolean flag = false;
public static void main(String[] args) {
CrossNum cNum = new CrossNum();
Thread thread01 = new Thread(new Print2nAnd1(cNum));
Thread thread02 = new Thread(new Print2n(cNum));
thread01.start();
thread02.start();
}
}
class Print2nAnd1 implements Runnable{
private CrossNum cNum;
public Print2nAnd1(CrossNum cNum) {
// TODO Auto-generated constructor stub
this.cNum = cNum;
}
@Override
public void run() {
while(cNum.num<101) {
if(!cNum.flag) {
System.out.println("奇数线程"+Thread.currentThread()+cNum.num);
cNum.num++;
cNum.flag = true;
// notifyAll();
}
}
}
}
class Print2n implements Runnable{
private CrossNum cNum;
public Print2n(CrossNum cNum) {
// TODO Auto-generated constructor stub
this.cNum = cNum;
}
@Override
public void run() {
while(cNum.num<101) {
if(cNum.flag) {
System.out.println("偶数线程"+Thread.currentThread()+cNum.num);
cNum.num++;
cNum.flag = false;
}
}
}
}
2、使用synchronized来实现,比第一种的资源用的少,因为有锁控制了阻塞,上一种一直在轮询,同样因为有锁,涉及到了进程状态的上下文切换,效率就会降低,这也是为什么要用CAS等乐观锁了。
public class CrossNum2 {
public int num = 1;
public boolean flag = false; //均不需要使用volitale来修饰,后面使用锁
public static void main(String[] args) {
CrossNum2 cNum2 = new CrossNum2();
Thread thread_jishu = new Thread(new Print01(cNum2));
Thread thread_oushu = new Thread(new Print02(cNum2));
thread_jishu.start();
thread_oushu.start();
}
}
class Print01 implements Runnable{
private CrossNum2 cNum2;
public Print01(CrossNum2 cNum2) {
this.cNum2 = cNum2;
}
@Override
public void run() {
while(cNum2.num<101) {
synchronized (cNum2) {
if(cNum2.flag) {
try {
cNum2.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
System.out.println(Thread.currentThread()+" "+ cNum2.num);
cNum2.num++;
cNum2.flag = true;
cNum2.notifyAll();
}
}
}
}
}
class Print02 implements Runnable{
private CrossNum2 cNum2;
public Print02(CrossNum2 cNum2) {
this.cNum2 = cNum2;
}
@Override
public void run() {
while(cNum2.num<101) {
synchronized (cNum2) {
if(!cNum2.flag) {
try {
cNum2.wait();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
System.out.println(Thread.currentThread()+" "+ cNum2.num);
cNum2.num++;
cNum2.flag = false;
cNum2.notifyAll();
}
}
}
}
}
3、使用ReentrantLock来实现线程间的交叉打印,其实和synchronized锁的效果差不多,就是写法有点不一样
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class CrossNum3 {
public int num = 1;
public boolean flag = false;
public Lock lock = new ReentrantLock();
public static void main(String[] args) {
CrossNum3 crossNum3 = new CrossNum3();
Thread thread01 = new Thread(new Print001(crossNum3));
Thread thread02 = new Thread(new Print002(crossNum3));
thread02.start();
thread01.start();
}
}
class Print001 implements Runnable{
private CrossNum3 cNum;
public Print001(CrossNum3 crossNum3) {
this.cNum = crossNum3;
}
@Override
public void run() {
while(cNum.num < 101) {
cNum.lock.lock();
try {
if(cNum.flag) {
System.out.println(Thread.currentThread()+" "+cNum.num);
cNum.num++;
cNum.flag = true;
}
}
}finally {
cNum.lock.unlock();
}
}
}
}
class Print002 implements Runnable{
private CrossNum3 cNum;
public Print002(CrossNum3 crossNum3) {
this.cNum = crossNum3;
}
@Override
public void run() {
while(cNum.num < 101) {
cNum.lock.lock();
try {
if(!cNum.flag) {
System.out.println(Thread.currentThread()+" "+cNum.num);
cNum.num++;
cNum.flag = false;
}
}
}finally {
cNum.lock.unlock();
}
}
}
}