java多線程交替打印兩個數

方法1,使用wait和notify

package com.thread;

public class T01 {

	public static void main(String[] args) {
		char[] char1 = "AAAAAA".toCharArray();
		char[] char2 = "BBBBBB".toCharArray();
		Object object = new Object();
		
		Thread thread1 = new Thread(()  -> {
				synchronized(object){//使用notify和wait時,必須要選獲取到鎖
					for (int i = 0; i < char1.length; i++) {
						try {
							System.out.print(char1[i]);
							object.notify();
							object.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
					object.notify();//必須加上,否則程序無法結束,兩個線程總有一個最後是wait狀態,所以此處必須加
			}
				
		},"t1");
		
		
		Thread thread2 = new Thread( () -> {
				synchronized(object){
					for (int i = 0; i < char2.length; i++) {
						try {
							System.out.print(char2[i]);
							object.notify();
							object.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
					object.notify();
			}
		},"t2");
		
		thread1.start();
		thread2.start();
		
	}
}

方法2,使用LockSupport方法

package com.thread;

import java.util.concurrent.locks.LockSupport;

public class T02 {
	static Thread thread1 ;
	static Thread thread2 ;
	public static void main(String[] args) {
		char[] char1 = "AAAAAA".toCharArray();
		char[] char2 = "BBBBBB".toCharArray();
		
		thread1 = new Thread(() -> {
				for (int i = 0; i < char1.length; i++) {
					System.out.print(char1[i]);
					LockSupport.unpark(thread2);
					LockSupport.park();
				}
		},"t1");
		
		 thread2 = new Thread(() -> {
				for (int i = 0; i < char2.length; i++) {
					LockSupport.park();
					System.out.print(char2[i]);
					LockSupport.unpark(thread1);
				}
		},"t2");
		
		thread1.start();
		thread2.start();
		
	}
	
	
}

方法3,使用CAS自旋鎖

package com.thread;

public class T03 {
	enum ReadEnum{
		T1,
		T2;
	}
	static volatile ReadEnum r  = ReadEnum.T1;
	public static void main(String[] args) {
		char[] char1 = "AAAAAA".toCharArray();
		char[] char2 = "BBBBBB".toCharArray();
		Thread thread1 = new Thread(() ->{
			for (int i = 0; i < char1.length; i++) {
				while (r != ReadEnum.T1) {
				}
				System.out.print(char1[i]);
				r = ReadEnum.T2;
			}
		},"t1");
		
		
		Thread thread2 = new Thread(() ->{
			for (int i = 0; i < char2.length; i++) {
				while (r != ReadEnum.T2) {
				}
				System.out.print(char2[i]);
				r = ReadEnum.T1;
			}
		},"t2");
		
		thread1.start();
		thread2.start();
		
		
	}
}

方法4,使用Condition方法

package com.thread;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;


public class T04 {

	public static void main(String[] args) {
		char[] char1 = "AAAAAA".toCharArray();
		char[] char2 = "BBBBBB".toCharArray();
		
		ReentrantLock lock = new ReentrantLock();
		Condition condition1 = lock.newCondition();
		Condition condition2 = lock.newCondition();
		
		Thread thread1 = new Thread(() ->{
			try {
				lock.lock();
				for (int i = 0; i < char1.length; i++) {
					System.out.print(char1[i]);
					condition2.signal();//喚醒線程2執行
					condition1.await();//線程1等待
				}
				condition2.signal();
			}catch (Exception e) {
				e.printStackTrace();
			}finally{
				lock.unlock();
			}
		},"t1");
		
		Thread thread2 = new Thread(() ->{
			try {
				lock.lock();
				for (int i = 0; i < char2.length; i++) {
					System.out.print(char2[i]);
					condition1.signal();
					condition2.await();
				}
				condition1.signal();
			} catch (Exception e) {
				e.printStackTrace();
			}finally{
				lock.unlock();
			}

		},"t2");
		
		thread1.start();
		thread2.start();
		
		
	}
}

打印結果:


Condition與notify相比的好處是,Condition可以指定需要喚醒的線程,而notify是無法指定的,只能隨機喚醒一個或者全喚醒(notifyAll)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章