多线程同步工作的两种方式

1、问题

      使用四个线程协调工作,线程1只打印“A”,线程2只打印“B”,线程3只打印“C”,线程4只打印“D”,当线程1工作时,其他线程阻塞,当线程2工作时,其他线程阻塞......使得打印结果为“ABCDABCDABCD....”,通过输入一个数,来控制重复的次数。

2、解决方式

   (1)通过synchronized修饰同步代码块,同步监视器是synchronized后括号的对象。该对象用于同步的方法如下:

            wait():调用该方法的线程前提是必须获得锁,该方法被调用后就释放锁,进入等待状态,直到该线程的同步监视器notify()和      notifyAll()方法来唤醒重新获得锁,继续执行。

       notify(): 唤醒在同步监视器上等待的单个线程,如果有许多线程,就随机的唤醒一个。

    notifyAll(): 唤醒在此同步监视器上所有等待的线程。被唤醒的线程将无法继续进行,直到当前线程放弃此对象上的锁定。

   (2)通过Lock对象保证同步,Condition对象充当同步监视器的功能。Condition对象的方法有

            await(): 与隐式同步监视器的wait()类似,调用该方法,线程进入等待状态。

   signal(): 与notify()类似。

   signalAll(): 与notifyAll()类似。

     为每个线程设置一个boolean类型的控制变量,用于控制该线程是否阻塞,每次执行完一个线程后重新设置控制变。

量的值,使得它下面一个线程可以继续执行。

3、代码。

     实现方式1:使用隐式同步监视器

    

import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class Main {

	static int N = 0;
	// 定义4个控制变量
	static boolean flagA = true;
	static boolean flagB = false;
	static boolean flagC = false;
	static boolean flagD = false;
	
	public static void main(String[] args) {
		
		
		Scanner scanner = new Scanner(System.in);
		N = scanner.nextInt();
		scanner.close();
		Main m = new Main();
		// 创建一个有4个线程的线程池
		ExecutorService pool = Executors.newFixedThreadPool(4);
		pool.submit(m.new ThreadA(m));
		pool.submit(m.new ThreadB(m));
		pool.submit(m.new ThreadC(m));
		pool.submit(m.new ThreadD(m));
		
		pool.shutdown();
		
		
	}
	
	class ThreadA implements Runnable{
		private Main m;
		public ThreadA(Main m){
			this.m = m;
		}
		@Override
		public void run() {
			for(int i=0;i<N;i++){
				
				// 由于wait方法进入等待时,会释放得到的锁,即只有当各个控制变量为true时,才不会阻塞
				synchronized(m){
					while(!flagA){
						try {
							m.wait();
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						};
					}
					
					try {
						Thread.sleep(200);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					
					System.out.print("A");
					flagA = false;
					flagB = true;
					flagC = false;
					flagD = false;
					m.notifyAll();
				}
			}
		}
		
	}
	
	class ThreadB implements Runnable{
		private Main m;
		public ThreadB(Main m){
			this.m = m;
		}
		@Override
		public void run() {
			for(int i=0;i<N;i++){
				synchronized(m){
					while(!flagB){
						try {
							m.wait();
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						};
					}
					try {
						Thread.sleep(200);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.print("B");
					flagA = false;
					flagB = false;
					flagC = true;
					flagD = false;
					m.notifyAll();
				}
			}
		}
		
	}
	
	class ThreadC implements Runnable{
		private Main m;
		public ThreadC(Main m){
			this.m = m;
		}
		@Override
		public void run() {
			for(int i=0;i<N;i++){
				synchronized(m){
					while(!flagC){
						try {
							m.wait();
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						};
					}
					try {
						Thread.sleep(200);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.print("C");
					flagA = false;
					flagB = false;
					flagC = false;
					flagD = true;
					m.notifyAll();
				}
			}
		}
		
	}
	
	class ThreadD implements Runnable{
		private Main m;
		public ThreadD(Main m){
			this.m = m;
		}
		@Override
		public void run() {
			for(int i=0;i<N;i++){
				synchronized(m){
					while(!flagD){
						try {
							m.wait();
						} catch (InterruptedException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						};
					}
					try {
						Thread.sleep(200);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					System.out.print("D");
					flagA = true;
					flagB = false;
					flagC = false;
					flagD = false;
					m.notifyAll();
				}
			}
		}
		
	}
	
}

实现方式2:用显示同步监视器

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class MainLock {

	private final Lock lock = new ReentrantLock();
	private final Condition cond = lock.newCondition();
	static int N = 0;
	boolean flagA = true;
	boolean flagB = false;
	boolean flagC = false;
	boolean flagD = false;


	public static void main(String[] args) {

		N = 10;
		ExecutorService pool = Executors.newFixedThreadPool(4);
        MainLock main = new MainLock();
		pool.submit(main.new ThreadA());
		pool.submit(main.new ThreadB());
		pool.submit(main.new ThreadC());
		pool.submit(main.new ThreadD());
		
		pool.shutdown();

	}

	class ThreadA implements Runnable{

		@Override
		public void run() {
			for(int i=0;i<N;i++){
				lock.lock();
				try {
					while(!flagA){
						  cond.await();
					}
					System.out.print("A");
					flagA = false;
					flagB = true;
					flagC = false;
					flagD = false;
					Thread.sleep(200);
					cond.signalAll();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}finally{
					lock.unlock();
				}

			}

		}
	}
	class ThreadB implements Runnable{

		@Override
		public void run() {
			for(int i=0;i<N;i++){
				lock.lock();
				try {
					while(!flagB){
						  cond.await();
					}
					System.out.print("B");
					flagA = false;
					flagB = false;
					flagC = true;
					flagD = false;
					Thread.sleep(200);
					cond.signalAll();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}finally{
					lock.unlock();
				}

			}

		}
	}
	class ThreadC implements Runnable{

		@Override
		public void run() {
			for(int i=0;i<N;i++){
				lock.lock();
				try {
					while(!flagC){
						  cond.await();
					}
					System.out.print("C");
					flagA = false;
					flagB = false;
					flagC = false;
					flagD = true;
					Thread.sleep(200);
					cond.signalAll();
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}finally{
					lock.unlock();
				}

			}

		}
	}
	class ThreadD implements Runnable{

		@Override
		public void run() {
			for(int i=0;i<N;i++){
				lock.lock();
				try {
					while(!flagD){
						  cond.await();
					}
					System.out.print("D");
					flagA = true;
					flagB = false;
					flagC = false;
					flagD = false;
					Thread.sleep(200);
					cond.signalAll();
				} catch (Exception e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}finally{
					lock.unlock();
				}

			}

		}
	}



}

留下足迹,特此记之。





你可能感兴趣的:(多线程同步工作的两种方式)