方法一
首先要确定临界资源,然后进行同步,与临界资源的不同要进行阻塞,相同的输出,并进行相应的调整
package mypack;
//临界类
public class Letters {
private char letter='A';
public void nextLetter(){
if(letter=='A')
letter='B';
else if(letter=='B')
letter='C';
else letter='A';
}
public char getLetter(){
return letter;
}
public void print(){
System.out.print(letter+" ");
}
}
package mypack;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class PrintLetters {
public static void main(String[] args) {
// TODO Auto-generated method stub
Letters letters=new Letters();
ExecutorService exec = Executors.newFixedThreadPool(3);
exec.execute(new ThreadPrint(letters,'A'));
exec.execute(new ThreadPrint(letters,'B'));
exec.execute(new ThreadPrint(letters,'C'));
exec.shutdown();
}
}
class ThreadPrint implements Runnable{
private Letters letters;
private char name;
public ThreadPrint(Letters l,char ch){
letters=l;
name=ch;
}
@Override
public void run() {
// TODO Auto-generated method stub
try{
for(int i=0;i<10;i++){
synchronized(letters){
while(letters.getLetter()!=name)//注意这里要用getLetter()的方法,随时获得临界资源变化的信息
letters.wait();
letters.print();
letters.nextLetter();
letters.notifyAll();
}
}
}catch(InterruptedException e){
System.out.println("Interrupted");
}
}
}
方法二:
运用内部类,访问临界变量,不需要传递临界变量
package mypack;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
public class PrintLetters {
private char currLetter='A';
private ReentrantLock lock=new ReentrantLock();
private Condition conditionA=lock.newCondition();
private Condition conditionB=lock.newCondition();
private Condition conditionC=lock.newCondition();
public static void main(String[] args) {
// TODO Auto-generated method stub
PrintLetters letters = new PrintLetters();
ExecutorService exec = Executors.newFixedThreadPool(3);
exec.execute(letters.new ThreadA('A'));
exec.execute(letters.new ThreadB('B'));
exec.execute(letters.new ThreadC('C'));
exec.shutdown();
}
private class ThreadA implements Runnable{
private char name;
public ThreadA(char ch){
name=ch;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++){
try{
lock.lock();
while(currLetter!=name)
try {
conditionA.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.print(name);
currLetter='B';
conditionB.signal();
}finally{
lock.unlock();
}
}
}
}
private class ThreadB implements Runnable{
private char name;
public ThreadB(char ch){
name=ch;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++){
try{
lock.lock();
while(currLetter!=name)
try {
conditionB.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.print(name);
currLetter='C';
conditionC.signal();
}
finally{
lock.unlock();
}
}
}
}
private class ThreadC implements Runnable{
private char name;
public ThreadC(char ch){
name=ch;
}
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++){
try{
lock.lock();
while(currLetter!=name)
try {
conditionC.await();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.print(name+" ");
currLetter='A';
conditionA.signal();
}
finally{
lock.unlock();
}
}
}
}
}
运用信号量Semaphore
package mypack;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
public class PrintLetters {
private Semaphore semaphoreA=new Semaphore(1);
private Semaphore semaphoreB=new Semaphore(0);
private Semaphore semaphoreC=new Semaphore(0);
public static void main(String[] args) {
// TODO Auto-generated method stub
PrintLetters letters = new PrintLetters();
ExecutorService exec = Executors.newFixedThreadPool(3);
exec.execute(letters.new ThreadA());
exec.execute(letters.new ThreadB());
exec.execute(letters.new ThreadC());
<span style="white-space:pre"> </span>exec.shutdown();
}
private class ThreadA implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++){
try {
semaphoreA.acquire();
System.out.print('A');
semaphoreB.release();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
private class ThreadB implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++){
try {
semaphoreB.acquire();
System.out.print('B');
semaphoreC.release();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
private class ThreadC implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<10;i++){
try {
semaphoreC.acquire();
System.out.println("C ");
semaphoreA.release();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}