线程同步的6种方法

1.synchronize

做用在静态方法上和作用在代码块上(锁对象是类名.class)效果一样

public class SynThread1{
	
	public static void main(String[] args) {
		new Thread() {
			public void run() {
				print1();
			};
		}.start();
		new Thread() {
			public void run() {
				print2();
			};
		}.start();
	}

	public static synchronized void print1() {
		for(int i=0;i<5;i++) {
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.print(i+" ");
		}
		System.out.println();
	}
	
	public static void print2() {
		synchronized (SynThread1.class) {
			for(int i=5;i<10;i++) {
				try {
					Thread.sleep(500);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.print(i+" ");
			}
			System.out.println();
		}
	}
}

结果
在这里插入图片描述

2.ReentrantLock重入锁

lock()方法加锁,unlock()释放锁。建议unlock()在finally语句块中。

public class LockThread1 {
	static ReentrantLock lock = new ReentrantLock();
	
	public static void main(String[] args) {
		new Thread(new Runnable() {
			@Override
			public void run() {
				print1();
			}
		}).start();
		new Thread() {
			public void run() {
				print2();
			};
		}.start();
	}
	
	public static void print1() {
		for(int i=1;i<5;i++) {
			lock.lock();
			try {
				try {
					TimeUnit.SECONDS.sleep(1);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.print(i);
			}finally {
				lock.unlock();
			}
		}
	} 
	public static void print2() {
		for(int i=5;i<9;i++) {
			lock.lock();
			try {
				try {
					TimeUnit.SECONDS.sleep(1);
				} catch (InterruptedException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
				System.out.print(i);
			}finally {
				lock.unlock();
			}
		}
	} 
}

结果
在这里插入图片描述

3.可能会同步的volatile

每次要线程要访问volatile修饰的变量时都是从内存中读取,而不是存缓存当中读取,因此每个线程访问到的变量值都是一样的。但是它不保证同步,只是接近而已。运行了10次,其中8次同步。

public class VolThread1 {
	volatile static int a = 0;
	
	public static void main(String[] args) {
		new Thread(new Runnable() {
			@Override
			public void run() {
				add1();
				System.out.println(a);
			}
		}).start();
		new Thread(new Runnable() {
			@Override
			public void run() {
				add2();
				System.out.println(a);
			}
		}).start();
	}
	
	public static void add1() {
		for(int i=1;i<=10;i++) {
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			a = a+i;
		}
	}
	
	public static void add2() {
		for(int i=1;i<=10;i++) {
			try {
				Thread.sleep(10);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			a = a+i;
		}
	}
}

正常结果
在这里插入图片描述
其中一个异常结果
在这里插入图片描述
不推荐的方法

4.Semaphore信号量(可参数设置几个线程同时运行)

new Semaphore(int permits)参数是允许同时进行的线程数,如果线程未获得准入许可,进入等待,acquire()方法尝试获得许可,release()方法释放一个许可

public class SemThread1 {
	//控制同时运行的线程数
	final static Semaphore semap = new Semaphore(2);
	
	public static void main(String[] args) {
		new Thread() {
			public void run() {
				print1();
			};
		}.start();
		new Thread() {
			public void run() {
				print1();
			};
		}.start();
		new Thread() {
			public void run() {
				print2();
			};
		}.start();
	}
	
	public static void print1() {
		try {
			semap.acquire();
			for(int i=1;i<5;i++) {
				TimeUnit.SECONDS.sleep(1);
				System.out.print(i);
			}
			System.out.println();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			semap.release();
		}
	}
	
	public static void print2() {
		try {
			semap.acquire();
			for(int i=5;i<9;i++) {
				TimeUnit.SECONDS.sleep(1);
				System.out.print(i);
			}
			System.out.println();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}finally {
			semap.release();
		}
	}
}

这里的三个线程同时对多只能运行两个
结果
在这里插入图片描述

5.CountDownLatch门闩

new CountDownLatch(int count)指定门闩数,countDown()方法将门闩减一,await()方法等待门闩数减为0。

public class LatchThread {
	
	final static CountDownLatch latch = new CountDownLatch(1);
	
	public static void main(String[] args) {
		new Thread() {
			public void run() {
				print1();
			};
		}.start();
		new Thread() {
			public void run() {
				print2();
			};
		}.start();
	}
	
	public static void print1() {
		for(int i=1;i<5;i++) {
			try {
				TimeUnit.SECONDS.sleep(1);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.print(i);
		}
		latch.countDown();
		System.out.println();
	}
	
	public static void print2() {
		try {
			latch.await();
		} catch (InterruptedException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		for(int i=5;i<9;i++) {
			try {
				TimeUnit.SECONDS.sleep(1);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.print(i);
		}
		System.out.println();
	}
	
}

结果
在这里插入图片描述

6.FixedThreadPool定长线程池(多多少少算是吧)

Executors.newFixedThreadPool(int nThreads),nThreads指定可以有几个线程同时运行,如果是1的话,也算是有同步的效果。。。execute(Runnable command)方法执行线程。超过指定的nThreads会进入阻塞队列等待。

public class ExecutorThread {
	static ExecutorService fixedThreadPool = Executors.newFixedThreadPool(1);
	
	public static void main(String[] args) {
		fixedThreadPool.execute(new Runnable() {
			@Override
			public void run() {
				print1();
			}
		});
		fixedThreadPool.execute(new Runnable() {
			
			@Override
			public void run() {
				print2();
			}
		});
	}
	
	public static void print1() {
		for(int i=1;i<5;i++) {
			try {
				TimeUnit.SECONDS.sleep(1);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.print(i);
		}
		System.out.println();
	}
	
	public static void print2() {
		for(int i=5;i<9;i++) {
			try {
				TimeUnit.SECONDS.sleep(1);
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			System.out.print(i);
		}
		System.out.println();
	}
}

结果
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值